首页 > 编程知识 正文

汇编语言程序和汇编程序,pe打不开raw格式

时间:2023-05-05 15:27:52 阅读:163774 作者:790

RVA to RAW? 汇编程序输出PE文件导入/导出表一、PE文件的映像(Image)和文件

PE文件存储在磁盘上时,作为指令和数据的静态集合,排列得比较紧凑。 但是,当PE文件加载到内存中时:

编译器的添加指令等与原节合并,使内存内的节大小与文件内不同

子句之间的内存定位与文件中的子句定位不同,因此子句之间的距离变大的概率较大

二、RVA to RAW

简单地说,该算法通常不会更改节中的数据和节开头的相对地址。 因此,只需找到文件中节的起始位置,并将文件的起始位置添加到相对内存位置,即可获得文件中的数据位置

所以,步骤分为三个步骤

找出目标数据属于哪个部分(大于该部分的VirtualAddress,小于该部分的VitualAddress VirtualSize ) )。

引出该节中的虚拟地址,加入该节中的Pointer of Raw Data

如果指向*的文件偏移量在某个节之外,则表示该节的文件大小和内存大小存在很大差异

三、IAT,IID,INT

OPTINONAL_HEADER包含导入的表的地址,即第一个IID

IID :因为导入库的单位,所以与各个库对应的函数都存在于其索引内

INT :读取函数的数组,读取INT就能读取读取的函数名

此图为IID,在偏移618h处为00002040,并转换为raw(2040h-2000h ) 618h )

2066-666处是库名

666h可见kernel32.dll

在640h处为00002074h,找到674处,发现了GetStdHandle的函数名

总结来说:找到IID,去拿库的INT,读取库的INT,填到目标IAT

四、程序的读取思路

需要输入表单读取IID

查找iid需要找到选项标头的地址。读取DOS标头e_lfanew

将IID地址转换为原始-需要节标题表中的三个值

节标题表-PE文件标题中有OPTINONAL_Header的大小(不确定大小)

将IID地址转换为原始节标头表,并使其重要信息存在于结构中(RVA、P of ROW、RVA SIZE ) )。

将IID地址转换为原始-找到合适的部分并进行转换

转换为iid读取RAW-导线扫描INT

-每个INT遍历并读取内部所有函数名称的输出

在读取IED之前输出表读取,但之后只遍历地址名称

五:代码

注:此代码无输出可能为读取文件的缓冲区不够大,读到了未申请内存

本程序经过masm32/gddgs/msdis109.dll测试,经过了上一次程序的exe测试,输出正常

. 386.model flat,stdcall option casemap : none included :masm 32includewindows.Inc included 3360 masm 3232 masm 32libkernel32.ligddgscludelibd 3360masm 32libmasm 32 user32.incincludelibd : masm 32 lib _ sclib 进程声明们dw2hex PROTO :DWORD、DWORD; 从masm32.inc十六进制值转换为字符串的过程rva2raw PROTO :DWORD; 将RVA转换为文件偏移原始数据的过程。 参数为RVAreadIID PROTO; 读取IID的过程读函数协议; 读取每个IID对应名称的函数名称的过程; 读取IED的过程(因为只有一个IED,所以不需要读函数); 固定字符串们NoExport BYTE 'no EXport TABlE! ! !' 、0 banner byte ' plsinputapefile : ',0strn BYTE 0ah,00h; 文件的路径、句柄和内存提供了接受文件的缓冲区。 因为文件很大,所以必须申请大缓冲区们。 当然,也可以改变文件的指针读取到特定的位置,但我不太想读文件。 我很懒,可以打pathbyte20dup(0) filehandle DWORD )吗? 文件字节217502 dup (0; 中间地址们(RAW除外

说明以外均为RVA)NT_addr DWORD ? ;NT头(pe文件头首地址)OP_addr DWORD ? ;可选头首地址SE_addr DWORD ? ;节区头首地址EX_addr DWORD ? ;导出表地址IM_addr DWORD ? ;导入表地址SE_adds DWORD 30h DUP(0) ;储存各个节的RVA起始地址,RAW起始地址,Image大小,RAW大小的结构体(以下解释为什么是结构体)INT_addr DWORD ? ;INT的地址SE_num WORD ? ;节的数量var DWORD ? ;中间变量1vara DWORD ? ;中间变量2EX_namebase DWORD ? ;导出表名字数组首地址pointer DWORD ? ;指向导入表的第i个IID地址Lastpointer DWORD ? ;由于导出表名字不以0结尾,所以需要验证所取得地址和(Last)上一个地址是不是递增.codereadFuncName PROCINVOKE rva2raw,eax ;假设已经传入了eax是INTname的地址RVAADD eax,OFFSET filebuf ;加上我们自己程序内存读取PE文件的基地址MOV vara,eax ;临时保存,StdOut会修改寄存器LNextFunc: MOV eax,vara ;回复eaxMOV esi,DWORD PTR [eax] ;读取名字地址CMP esi,0h ;和0比较(INT name数组结束为0)JE LTailMOV edi,esiAND edi,0ff000000h ;相等返回CMP edi,80000000h JNE LOrdinalADD eax,4hMOV esi,DWORD PTR [eax]LOrdinal: INVOKE rva2raw,esi ;将读取的地址转化为RAW,加上我们自己程序内存读取PE文件的基地址ADD eax,OFFSET filebuf ADD eax,2h ;前两字节是ordinal,跳过MOV var,eax INVOKE StdOut,varINVOKE StdOut,addr strn ADD vara,4h ;更新eax的指向JMP LNextFuncLTail:retreadFuncName ENDPreadIID PROC ;假设传入的esi已经是IID的RAW,以下读取INT地址MOV eax,DWORD PTR [esi]MOV INT_addr,eaxADD esi,0chMOV eax,DWORD PTR [esi]INVOKE rva2raw,eaxADD eax,OFFSET filebufINVOKE StdOut,eaxINVOKE StdOut,addr strnADD esi,4hMOV eax,INT_addrretreadIID ENDPreadIED PROC ;假设传入的esi已经是IED的RAW,以下读取ADDRESS OF NAME地址ADD esi,20hMOV eax,DWORD PTR [esi]INVOKE rva2raw,eax ;address of name的RVA转化成 RAWMOV EX_namebase,eax ;保存名字数组的基地址MOV Lastpointer,eax ;保存前一个名字指针的地址LNextOut:ADD eax,OFFSET filebuf ;RAW加上我们自己程序内存读取PE文件的基地址MOV ebx,DWORD PTR [eax] ;读取MOV edi,ebx ;将edx放到edi中和lastpointer比较,如果单增说明还有一个要读,若否则说明结束SUB edi,Lastpointer CMP edi,0hJL LEndExINVOKE rva2raw,ebx ;读到到字符串地址也是RVA,要转到RAWADD eax,OFFSET filebufINVOKE StdOut,eax ;输出INVOKE StdOut,addr strnADD EX_namebase,4h ;下一个地址MOV eax,EX_namebase ;恢复eaxJMP LNextOutLEndEx:retreadIED ENDPrva2raw PROC rva:DWORD MOV eax,rva;eax里面存储需要转换的地址MOV ecx,0;ecx里面来计数LSec:SHR ecx,2CMP cx,SE_num;ecx和节头数比较 JE LEnd SHL ecx,2 ;如果等于节头数,说明找完了,退出MOV edx,DWORD PTR SE_adds[ecx*4] ;把节大小放到edx,地址放到ediMOV edi,DWORD PTR SE_adds[ecx*4+4h]Add edx,edi ;edx为上限,edi为下限CMP rva,ediJL LNextCMP rva,edx ;条件,输入的RVA大于该节的RVA起始地址,小于该节的RVA+VIRTUAL_SIZEJG LNextJMP LEndLNext:ADD ecx,4h ;没找到则下一个节的信息结构体JMP LSecLEnd:SUB eax,DWORD PTR SE_adds[ecx*4+4h] ;若找到了减去RVA,加上RAW pointerADD eax,DWORD PTR SE_adds[ecx*4+0ch]retrva2raw ENDPmain PROCINVOKE StdOut,addr bannerINVOKE StdOut,addr strnINVOKE StdIn,addr path,20;读入待分析文件INVOKE CreateFile,addr path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, 0MOV filehandle,eaxINVOKE SetFilePointer, filehandle, 0, 0, FILE_BEGININVOKE ReadFile, filehandle, addr filebuf, 217502, 0, 0MOV esi,OFFSET filebuf;至此,文件读入了内存之中,下面开始对内存进行读写ADD esi,3chMOV eax,DWORD PTR [esi]MOV esi,OFFSET filebufADD esi,eaxMOV ax,WORD PTR [esi+6h]MOV SE_num,ax;到此找到了NT头(PE FILE_HEADER)MOV NT_addr,esiMOV ebx,NT_addrADD ebx,18hMOV OP_addr,ebx;找到可选头,为后面遍历可选头做准备ADD esi,14hMOV eax,0MOV ax,WORD PTR [esi]MOV ebx,OP_addrADD ebx,eaxMOV SE_addr,ebx;找到节头,为了转换RVA和RAW做准备MOV esi,OP_addrADD esi,60hMOV eax,DWORD PTR [esi]MOV EX_addr,eaxADD esi,8hMOV eax,DWORD PTR [esi]MOV IM_addr,eax;开始遍历节头表MOV esi,SE_addrMOV ecx,0LSection:MOV edx,DWORD PTR [esi]CMP edx,0;比较有没有节头内容JE LfoundADD esi,8h;MOV eax,DWORD PTR [esi] ;虚拟内存大小MOV SE_adds[ecx],eaxADD esi,4hMOV eax,DWORD PTR [esi] ;虚拟内存基址MOV SE_adds[ecx+4h],eax ADD esi,4hMOV eax,DWORD PTR [esi] ;文件节区大小MOV SE_adds[ecx+8h],eaxADD esi,4hMOV eax,DWORD PTR [esi] ;文件节区基址偏移MOV SE_adds[ecx+0ch],eaxADD ecx,10hADD esi,14hJMP LSectionLfound:MOV ebx,IM_addr;提取导入表导出表的偏移和地址,准备转换;1.遍历节头,找到具体的节;2.转化成文件偏移,取值,读取INVOKE rva2raw,ebx ;找到了导入表的文件偏移(返回值为eax)MOV esi,OFFSET filebufADD esi,eaxMOV pointer,esi ;pointer存储IID每个元素的首地址NextChunk:MOV esi,pointer ;将esi设为每个IID首地址(RAW)读取MOV edi,DWORD PTR [esi+0ch] ;检测是否读完了CMP edi,0JE ReadEndINVOKE readIIDCMP INT_addr,0hJNE LEmptyDllMOV eax,DWORD PTR [esi]LEmptyDll:INVOKE readFuncName ;读当前IID元素的函数ADD pointer,14hJMP NextChunkReadEnd:INVOKE StdOut,addr strn;下面开始读导出表MOV ebx,EX_addrCMP ebx,0hJE LNO ;检查导出表是否为0INVOKE rva2raw,ebx ;eax为返回值MOV esi,OFFSET filebufADD esi,eaxINVOKE readIED ;将esi置为IED的首地址(RAW)读取JMP LendLNO:INVOKE StdOut,addr NoExportLend:INVOKE CloseHandle,filehandleINVOKE ExitProcess,0main ENDPEND main ![在这里插入图片描述](https://img-blog.csdnimg.cn/d5dfd0e740c045feb174a803235e37d1.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBATktVX2JsYWNrYmxhZGU=,size_20,color_FFFFFF,t_70,g_se,x_16)**其中看似乱码的是基于不同函数调用约定所生成的名称**

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。