逆向与反汇编实战(一)--PEiD分析复现
准备
简介:
PEiD(PE Identifier)是一款著名的查壳工具,其功能强大,几乎可以侦测出所有的壳,其数量已超过470 种PE 文档 的加壳类型和签名。
整个过程需要测试文件成品:https://www.lanzous.com/b07r7qu0d
首先使用PEiD检测之前做的一个异常捕捉测试程序。源码在下面,编译器为VC++ 6.0,编译方法为 Win32 Release
#include <stdio.h> class CExcepctionBase {
public:
virtual const char* GetExcepctionInfo() = ;
}; class CDiv0Excepction :public CExcepctionBase {
public:
CDiv0Excepction() {
printf("CExcepctionDiv0()\r\n");
}
virtual ~CDiv0Excepction() {
printf("~CDiv0Excepction()\r\n");
}
virtual const char* GetExcepctionInfo() {
return "div zero excepction";
}
}; class CAccessExcepction :public CExcepctionBase {
public:
CAccessExcepction() {
printf("CAccessExcepction()\r\n");
}
virtual ~CAccessExcepction() {
printf("~CAccessExcepction()\r\n");
}
virtual const char* GetExcepctionInfo() {
return "access excepction";
}
}; void TestExcepction(int n) {
try {
if ( == n) {
throw ;
}
if ( == n) {
throw 3.0f;
}
if ( == n) {
throw '';
}
if ( == n) {
throw 3.0;
}
if ( == n) {
throw CDiv0Excepction();
}
if ( == n) {
throw CAccessExcepction();
}
if ( == n) {
CAccessExcepction excAccess;
throw& excAccess;
}
}
catch (int n) {
printf("catch int %d\r\n", n);
}
catch (float f) {
printf("catch float %f\r\n", f);
}
catch (char c) {
printf("catch char %c\r\n", c);
}
catch (double d) {
printf("catch double %f\r\n", d);
}
catch (CExcepctionBase &exc) {
printf("catch error %s\r\n", exc.GetExcepctionInfo());
}
catch (CAccessExcepction *pExc) {
printf("catch error %s\r\n", pExc->GetExcepctionInfo());
}
catch (...) {
printf("catch ... ...");
}
printf("Test End!\r\n");
} int main()
{
for (int i = ; i <= ; ++i) {
TestExcepction(i);
} return ;
}
使用PEiD检测情况
文件判定分析
函数定位
从PEiD的分析情况,可以看到“Microsoft Visual C++ 6.0”的字符串,使用OD打开PEiD,找到字符串位置后下断点
00438FF6 |> \8BAC24 9C0400>mov ebp,dword ptr ss:[esp+0x49C]
00438FFD |> 6A push 0x18
00438FFF |. 285A4000 push upPEiD.00405A28 ; ASCII "Microsoft Visual C++ 6.0"
|> 8D4D lea ecx,dword ptr ss:[ebp+0x4]
|. E8 04D4FFFF call upPEiD.
实际上,运行到此处时,已经结束了文件判断分析阶段,得到了结果,在上一条指令(红线指引),我们可以返回到跳转之前的函数,即是文件判定函数。
文件判定函数分析
接着向上查找,找到函数的入口处,设置断点,开始文件判定函数的分析
00438C20 /$ 81EC sub esp,0x488
00438C26 |. push ebx
00438C27 |. push ebp
00438C28 |. push esi
00438C29 |. push edi
00438C2A |. B0 mov al,0x72 ; 定义特征码
00438C2C |. 2F mov byte ptr ss:[esp+0x2F],al
00438C30 |. mov byte ptr ss:[esp+0x31],al
00438C34 |. mov byte ptr ss:[esp+0x34],al
00438C38 |. mov byte ptr ss:[esp+0x39],al
00438C3C |. 3D mov byte ptr ss:[esp+0x3D],al
00438C40 |. B0 mov al,0x63 ; 定义特征码
00438C42 |. mov byte ptr ss:[esp+0x40],al
00438C46 |. mov byte ptr ss:[esp+0x41],al
00438C4A |. B0 mov al,0x73 ; 定义特征码
00438C4C |. mov byte ptr ss:[esp+0x43],al
00438C50 |. mov byte ptr ss:[esp+0x44],al
00438C54 |. B0 6C mov al,0x6C ; 定义特征码
00438C56 |. mov byte ptr ss:[esp+0x47],al
00438C5A |. mov byte ptr ss:[esp+0x48],al
00438C5E |. 8BB424 A00400>mov esi,dword ptr ss:[esp+0x4A0]
00438C65 |. 8B46 0C mov eax,dword ptr ds:[esi+0xC] ; PE首地址,即IMAGE_NT_HEADERS
00438C68 |. 8B56 mov edx,dword ptr ds:[esi+0x18] ; ".text"节首地址
00438C6B |. B1 6D mov cl,0x6D ; 定义特征码
00438C6D |. 884C24 mov byte ptr ss:[esp+0x36],cl
00438C71 |. 884C24 3E mov byte ptr ss:[esp+0x3E],cl
00438C75 |. B3 mov bl,0x41 ; 定义特征码
00438C77 |. C64424 2C 7B mov byte ptr ss:[esp+0x2C],0x7B
00438C7C |. C64424 2D 4F mov byte ptr ss:[esp+0x2D],0x4F
00438C81 |. C64424 2E mov byte ptr ss:[esp+0x2E],0x75
00438C86 |. C64424 mov byte ptr ss:[esp+0x30],0x50
00438C8B |. C64424 6F mov byte ptr ss:[esp+0x32],0x6F
00438C90 |. C64424 mov byte ptr ss:[esp+0x33],0x67
00438C95 |. C64424 mov byte ptr ss:[esp+0x35],0x61
00438C9A |. C64424 mov byte ptr ss:[esp+0x37],0x44
00438C9F |. C64424 mov byte ptr ss:[esp+0x38],0x69
00438CA4 |. C64424 3A 7D mov byte ptr ss:[esp+0x3A],0x7D
00438CA9 |. C64424 3B 5C mov byte ptr ss:[esp+0x3B],0x5C
00438CAE |. 885C24 3C mov byte ptr ss:[esp+0x3C],bl
00438CB2 |. 885C24 3F mov byte ptr ss:[esp+0x3F],bl
00438CB6 |. C64424 mov byte ptr ss:[esp+0x42],0x65
00438CBB |. C64424 2E mov byte ptr ss:[esp+0x45],0x2E
00438CC0 |. C64424 mov byte ptr ss:[esp+0x46],0x64
00438CC5 |. C64424 4D mov byte ptr ss:[esp+0x18],0x4D
00438CCA |. C64424 mov byte ptr ss:[esp+0x19],0x53
00438CCF |. C64424 1A mov byte ptr ss:[esp+0x1A],0x43
00438CD4 |. C64424 1B mov byte ptr ss:[esp+0x1B],0x46
00438CD9 |. 0FB740 movzx eax,word ptr ds:[eax+0x6] ; eax中为IMAGE_NT_HEADERS首地址,[eax+0x6]为Section Number(节数目) = 3
00438CDD |. 8D0C80 lea ecx,dword ptr ds:[eax+eax*] ; 节数目乘5
00438CE0 |. 8B6CCA E8 mov ebp,dword ptr ds:[edx+ecx*-0x18] ; 得到".data"所占大小
00438CE4 |. 8D44CA D8 lea eax,dword ptr ds:[edx+ecx*-0x28] ; 保存".data"节的首地址
00438CE8 |. 8B78 mov edi,dword ptr ds:[eax+0x14] ; ".data"在磁盘中的偏移
00438CEB |. 8B46 mov eax,dword ptr ds:[esi+0x4] ; 第二个参数指向结构中的第二项数据
00438CEE |. 03FD add edi,ebp ; ".data"偏移地址+".data"节所占大小=".data"节末尾
00438CF0 |. 8BAC24 9C0400>mov ebp,dword ptr ss:[esp+0x49C] ; 获取第一个参数
00438CF7 |. 8D8F lea ecx,dword ptr ds:[edi+0x3900] ; .data节在内存中的位置
00438CFD |. 3BC1 cmp eax,ecx ; 判断第二个参数是否不小于.data节(.data之后就是OEP),如果成功,跳过OEP检查
00438CFF |. 1A jnb XupPEiD.00438D1B ; 跳过OEP检查
00438D01 |. 8B55 mov edx,dword ptr ss:[ebp+0x20] ; 获取到程序入口地址
00438D04 |. 85D2 test edx,edx ; 检查OEP
00438D06 |. je XupPEiD.00438D1B
00438D08 |. 8B4E mov ecx,dword ptr ds:[esi+0x18] ; .text节首地址
00438D0B |. 8B79 mov edi,dword ptr ds:[ecx+0x14] ; .text节文件偏移
00438D0E |. add edi,dword ptr ds:[ecx+0x10] ; .text节文件偏移+.text节大小=.text节末尾
00438D11 |. 3BD7 cmp edx,edi ; 判断OEP是否在.text节中
00438D13 |. 0F82 E4020000 jb upPEiD.00438FFD ; 如果在,跳转,检查结束
通过,分析实际上这个函数就做了两件事,一是判定第二个参数是否在.data节中,二是判断OEP是否在.text节中。对于节区以及对应位置功能的判断,可以使用PEView,010 Editor以及结合OD寄存器区判断,这里不给出判定过程了。但是,在这里却没有用到特征码,我们将最后一步的跳转命令nop。分析OEP检查错误情况的代码。
OEP检查错误和编译器判断
00438D13 nop ; 如果在,跳转,检查结束
00438D14 nop
00438D15 nop
00438D16 nop
00438D17 nop
00438D18 nop ; ************下面的代码是OEP检查失败的情况************
00438D19 |. 8BFA mov edi,edx ; OEP偏移地址存入EDI,0x1634
00438D1B |> 2BC7 sub eax,edi ; 保存.data节的末尾地址
00438D1D |. 83F8 cmp eax,0x9 ; 判断OEP是否在.data节中
00438D20 |. 0F82 D7020000 jb upPEiD.00438FFD ; 不在就跳转
00438D26 |. 8B16 mov edx,dword ptr ds:[esi] ; edx保存IMAGE_DOS_HEADER首地址
00438D28 |. 8D0C3A lea ecx,dword ptr ds:[edx+edi] ; 得到OEP的地址
00438D2B |. 8B11 mov edx,dword ptr ds:[ecx] ; 将OEP前四个直接存入edx中,edx=0x6AEC8B55
00438D2D |. 81FA 496E7374 cmp edx,0x74736E49 ; OEP与特征码比较
00438D33 |. jnz XupPEiD.00438D4A ; 条件成立,跳转,不成立则继续比较OEP后双字的数据
00438D35 |. 616C6C5>cmp dword ptr ds:[ecx+0x4],0x536C6C61 ; OEP与特征码比较
00438D3C |. 0C jnz XupPEiD.00438D4A ; 成立则跳转
00438D3E |. 6A push 0x17 ; 压入字符串长度
00438D40 |. B45A4000 push upPEiD.00405AB4 ; ASCII "InstallShield 2003 Stub"
00438D45 |. E9 BA020000 jmp upPEiD. ; 跳转到显示字符串函数处
00438D4A |> 81FA cmp edx,0x61746164 ; OEP与特征码比较
00438D50 |. jnz XupPEiD.00438D79
00438D52 |. 312E636>cmp dword ptr ds:[ecx+0x4],0x61632E31 ; 下面实际上就是一些其他版本的特征码比较了
00438D59 |. 1E jnz XupPEiD.00438D79
00438D5B |. B45A4000 push upPEiD.00405AB4 ; ASCII "InstallShield 2003 Stub"
00438D60 |. 8D4D lea ecx,dword ptr ss:[ebp+0x4]
00438D63 |. E8 38E9FFFF call upPEiD.004376A0
00438D68 |. 5F pop edi
00438D69 |. 5E pop esi
00438D6A |. C645 mov byte ptr ss:[ebp],0x1
00438D6E |. 5D pop ebp
00438D6F |. B0 mov al,0x1
00438D71 |. 5B pop ebx
00438D72 |. 81C4 add esp,0x488
00438D78 |. C3 retn
00438D79 |> 3D cmp eax,0x200
00438D7E |. BD mov ebp,0x200
00438D83 |. ja XupPEiD.00438D87
00438D85 |. 8BE8 mov ebp,eax
00438D87 |> 6A 1D push 0x1D
00438D89 |. 8D4424 lea eax,dword ptr ss:[esp+0x30]
00438D8D |. push eax
00438D8E |. 8D8C24 lea ecx,dword ptr ss:[esp+0x98]
00438D95 |. E8 26E5FFFF call upPEiD.004372C0
00438D9A |. 8B16 mov edx,dword ptr ds:[esi]
00438D9C |. 8D4C24 lea ecx,dword ptr ss:[esp+0x10]
00438DA0 |. push ecx
00438DA1 |. push ebp
00438DA2 |. 03D7 add edx,edi
00438DA4 |. push edx
00438DA5 |. 8D8C24 9C000000 lea ecx,dword ptr ss:[esp+0x9C]
00438DAC |. E8 4FE6FFFF call upPEiD.
00438DB1 |. 84C0 test al,al
00438DB3 |. je XupPEiD.00438DDB
00438DB5 |. 8BB424 9C040000 mov esi,dword ptr ss:[esp+0x49C]
00438DBC |. 6A 1B push 0x1B
00438DBE |. 985A4000 push upPEiD.00405A98 ; ASCII "Silicon Realms Install Stub"
00438DC3 |. 8D4E lea ecx,dword ptr ds:[esi+0x4]
00438DC6 |. E8 45D6FFFF call upPEiD.
00438DCB |. 5F pop edi
00438DCC |. C606 mov byte ptr ds:[esi],0x1
00438DCF |. 5E pop esi
00438DD0 |. 5D pop ebp
00438DD1 |. B0 mov al,0x1
00438DD3 |. 5B pop ebx
00438DD4 |. 81C4 add esp,0x488
00438DDA |. C3 retn
00438DDB |> 8B46 mov eax,dword ptr ds:[esi+0x4]
00438DDE |. 2BC7 sub eax,edi
00438DE0 |. 3D cmp eax,0x4000
00438DE5 |. BD mov ebp,0x4000
00438DEA |. ja XupPEiD.00438DEE
00438DEC |. 8BE8 mov ebp,eax
00438DEE |> 6A push 0x4
00438DF0 |. 8D4424 1C lea eax,dword ptr ss:[esp+0x1C]
00438DF4 |. push eax
00438DF5 |. 8D8C24 lea ecx,dword ptr ss:[esp+0x98]
00438DFC |. E8 BFE4FFFF call upPEiD.004372C0
00438E01 |. 8B16 mov edx,dword ptr ds:[esi]
00438E03 |. 8D4C24 lea ecx,dword ptr ss:[esp+0x10]
00438E07 |. push ecx
00438E08 |. push ebp
00438E09 |. 03D7 add edx,edi
00438E0B |. push edx
00438E0C |. 8D8C24 9C000000 lea ecx,dword ptr ss:[esp+0x9C]
00438E13 |. E8 E8E5FFFF call upPEiD.
00438E18 |. 84C0 test al,al
00438E1A |. je XupPEiD.00438E40
00438E1C |. 8BB424 9C040000 mov esi,dword ptr ss:[esp+0x49C]
00438E23 |. 845A4000 push upPEiD.00405A84 ; ASCII "InstallShield AFW"
00438E28 |. 8D4E lea ecx,dword ptr ds:[esi+0x4]
00438E2B |. E8 70E8FFFF call upPEiD.004376A0
00438E30 |. 5F pop edi
00438E31 |. C606 mov byte ptr ds:[esi],0x1
00438E34 |. 5E pop esi
00438E35 |. 5D pop ebp
00438E36 |. B0 mov al,0x1
00438E38 |. 5B pop ebx
00438E39 |. 81C4 add esp,0x488
00438E3F |. C3 retn
00438E40 |> 8B46 0C mov eax,dword ptr ds:[esi+0xC] ; eax为IMAGE_NT_HEADERS地址=0x64800D8
00438E43 |. 8B40 mov eax,dword ptr ds:[eax+0x28] ; eax为代码段的地址
00438E46 |. push eax
00438E47 |. 8BCE mov ecx,esi
00438E49 |. E8 32A40100 call upPEiD. ; 计算偏移位置,得到正确的OEP
00438E4E |. 8BF8 mov edi,eax
00438E50 |. 8B46 mov eax,dword ptr ds:[esi+0x18] ; 获取.text节首地址,0x064801D0
00438E53 |. 8B48 mov ecx,dword ptr ds:[eax+0x14] ; .text节文件偏移地址
00438E56 |. add ecx,dword ptr ds:[eax+0x10] ; .text节文件偏移地址+.text节大小=.text节末尾偏移地址
00438E59 |. 3BF9 cmp edi,ecx ; 比较OEP是否在.text节中
00438E5B |. 0F82 jb upPEiD.00438FF6 ; 跳转到显示编译器版本处,此处即显示"Microsoft Visual C++ 6.0”
因为在第一部分对OEP的检测中,已经完成的跳转,实际上是不会执行这一段代码的,因此对于真正的文件判定代码,是会调用上面这段函数的。
要找到函数的调用处,因为函数在最后ret时,都会出栈函数调用处的调用地址,所以直接在函数结尾设置断点,执行观察栈区。
转到0x452F46
存放数据处
"真"文件分析函数
对上面分析函数进行分析
00452E90 /$ :A1 mov eax,dword ptr fs:[] ; 入口地址
00452E96 |. 6A FF push -0x1
00452E98 |. C8CD4600 push upPEiD.0046CDC8 ; 异常处理
00452E9D |. push eax
00452E9E |. : >mov dword ptr fs:[],esp
00452EA5 |. 83EC sub esp,0x10 ; 局部变量空间
00452EA8 |. push esi
00452EA9 |. 8B7424 mov esi,dword ptr ss:[esp+0x24] ; 第一个参数
00452EAD |. 8B46 mov eax,dword ptr ds:[esi+0x14]
00452EB0 |. 8B40 mov eax,dword ptr ds:[eax+0x10] ; 获取起始相对虚拟偏移地址
00452EB3 |. push edi ; 压入参数一
00452EB4 |. 8BF9 mov edi,ecx ; 获取this指针
00452EB6 |. push eax ; 压入代码起始RVA
00452EB7 |. 8BCE mov ecx,esi
00452EB9 |. E8 C2030000 call upPEiD. ; 检查PE文件格式,将OEP的RWA与RVA进行转换
00452EBE |. 3B46 cmp eax,dword ptr ds:[esi+0x4] ; 函数返回调整之后的OEP
00452EC1 |. jb XupPEiD.00452ED8 ; 条件成立,跳转到分析阶段
00452EC3 |. 5F pop edi ; =============分析失败代码===========
00452EC4 |. 32C0 xor al,al
00452EC6 |. 5E pop esi
00452EC7 |. 8B4C24 mov ecx,dword ptr ss:[esp+0x10]
00452ECB |. :890D >mov dword ptr fs:[],ecx
00452ED2 |. 83C4 1C add esp,0x1C
00452ED5 |. C2 retn 0x8 ; =======================================
00452ED8 |> push ebx
00452ED9 |. 8B5C24 mov ebx,dword ptr ss:[esp+0x30]
00452EDD |. mov dword ptr ds:[ebx+0x20],eax ; 保存调整之后的OEP
00452EE0 |. 8B4E mov ecx,dword ptr ds:[esi+0x4]
00452EE3 |. 8B16 mov edx,dword ptr ds:[esi]
00452EE5 |. 2BC8 sub ecx,eax
00452EE7 |. push ecx
00452EE8 |. 03D0 add edx,eax
00452EEA |. push edx ; 载入内存后的程序入口地址
00452EEB |. 8D4C24 lea ecx,dword ptr ss:[esp+0x14]
00452EEF |. push ecx
00452EF0 |. 8BCF mov ecx,edi
00452EF2 |. E8 E9740000 call upPEiD.0045A3E0 ; 将OEP代码与特征码进行对比--PEiD可以检查出分析程序是否在可识别的编译器范围内
00452EF7 |. 8B4424 mov eax,dword ptr ss:[esp+0x14]
00452EFB |. 8B4C24 mov ecx,dword ptr ss:[esp+0x10]
00452EFF |. 8BD0 mov edx,eax
00452F01 |. 2BD1 sub edx,ecx
00452F03 |. C1FA sar edx,0x2
00452F06 |. push edx
00452F07 |. push eax
00452F08 |. push ecx
00452F09 |. C74424 >mov dword ptr ss:[esp+0x30],0x0
00452F11 |. E8 9AF5FFFF call upPEiD.004524B0 ; 根据函数0x45A3E0对OEP处特征码的对比结果,将特征匹配的处理流程的函数指针,在数组中的下标值都存放在地址ESP+1C的数组中
00452F16 |. 8B7C24 1C mov edi,dword ptr ss:[esp+0x1C]
00452F1A |. 8B4424 mov eax,dword ptr ss:[esp+0x20]
00452F1E |. 83C4 0C add esp,0xC
00452F21 |. 3BF8 cmp edi,eax
00452F23 |. je XupPEiD.00452F5C ; 没有匹配的特征函数,结束分析
00452F25 |> 8B07 /mov eax,dword ptr ds:[edi]
00452F27 |. |push eax
00452F28 |. |push esi
00452F29 |. |push ebx
00452F2A |. FF15 8C1E4000 |call dword ptr ds:[0x401E8C] ; 检查.rdata节是否存在
00452F30 |. 83C4 0C |add esp,0xC
00452F33 |. 84C0 |test al,al
00452F35 |. |jnz XupPEiD.00452F7F ; 如果不存在,结束查询分析
00452F37 |. 8B07 |mov eax,dword ptr ds:[edi]
00452F39 |. |push eax
00452F3A |. |push esi
00452F3B |. 8D0C40 |lea ecx,dword ptr ds:[eax+eax*]
00452F3E |. |push ebx
00452F3F |. FF148D 8C1E4000 |call dword ptr ds:[ecx*+0x401E8C] ; 调用分析函数,存放数据的首地址在0x401E8C
00452F46 |. 83C4 0C |add esp,0xC
00452F49 |. 84C0 |test al,al
00452F4B |. |jnz XupPEiD.00452F7F
00452F4D |. 8B4424 |mov eax,dword ptr ss:[esp+0x14]
00452F51 |. 83C7 |add edi,0x4
00452F54 |. 3BF8 |cmp edi,eax
00452F56 |.^ CD \jnz XupPEiD.00452F25 ; 循环跳转。一直循环到匹配到对应的处理函数
上面的函数,整个过程:
- 对OEP的特征码比较
- 通过比较结果匹配储存函数指针的数组中的过程,将下标存储到数组
- 检测程序中是否存在.rdata节
- 从存储下标的数组中取出下标,调用对应的函数。
在第一步中,会产生一个使用OEP的哪些机器码作为特征码进行比较的问题(特征码的定义)。因此,我们进一步分析函数0x45A3E0
00452EF2 |. E8 E9740000 call upPEiD.0045A3E0 ; 将OEP代码与特征码进行对比--PEiD可以检查出分析程序是否在可识别的编译器范围内
特征码分析
0045A3E0 /$ 6A FF push -0x1
0045A3E2 |. 38D24600 push upPEiD.0046D238 ; SE 处理程序安装
0045A3E7 |. :A1 mov eax,dword ptr fs:[]
0045A3ED |. push eax
0045A3EE |. : >mov dword ptr fs:[],esp
0045A3F5 |. 83EC sub esp,0x14
0045A3F8 |. push ebx
0045A3F9 |. push ebp
0045A3FA |. 33DB xor ebx,ebx
0045A3FC |. push esi
0045A3FD |. push edi
0045A3FE |. 8BF1 mov esi,ecx ; 获取this指针
0045A400 |. 895C24 mov dword ptr ss:[esp+0x10],ebx ; 将数组清零
0045A404 |. 895C24 mov dword ptr ss:[esp+0x18],ebx
0045A408 |. 895C24 1C mov dword ptr ss:[esp+0x1C],ebx
0045A40C |. 895C24 mov dword ptr ss:[esp+0x20],ebx
0045A410 |. 8B7C24 mov edi,dword ptr ss:[esp+0x38] ; 获取OEP,保存到EDI
0045A414 |. 0FB607 movzx eax,byte ptr ds:[edi] ; 获取OEP地址处的数据
0045A417 |. 8B4486 mov eax,dword ptr ds:[esi+eax*+0x14] ; 对this指针偏移计算
0045A41B |. 83F8 FF cmp eax,-0x1
0045A41E |. 8B6C24 3C mov ebp,dword ptr ss:[esp+0x3C] ; OEP差值
0045A422 |. 895C24 2C mov dword ptr ss:[esp+0x2C],ebx ; EBX=0,将局部变量清0
0045A426 |. 0F je XupPEiD.0045A437
0045A428 |. push ebp
0045A429 |. push edi
0045A42A |. push eax
0045A42B |. 8D4C24 lea ecx,dword ptr ss:[esp+0x20] ; 获取数组首地址
0045A42F |. push ecx
0045A430 |. 8BCE mov ecx,esi ; 将ECX赋值为this指针
0045A432 |. E8 99FDFFFF call upPEiD.0045A1D0 ; 检查OEP处代码是否与特征码相同(将OEP处的字节码与特征码对比,从而比较OEP处的机器码)
0045A437 |> 8B86 mov eax,dword ptr ds:[esi+0x414]
0045A43D |. 83F8 FF cmp eax,-0x1
0045A440 |. 0F je XupPEiD.0045A451
0045A442 |. push ebp
0045A443 |. push edi
0045A444 |. push eax
0045A445 |. 8D5424 lea edx,dword ptr ss:[esp+0x20]
0045A449 |. push edx
0045A44A |. 8BCE mov ecx,esi
0045A44C |. E8 7FFDFFFF call upPEiD.0045A1D0 ; 检查OEP处代码是否与特征码相同(将OEP处的字节码与特征码对比,从而比较OEP处的机器码)
机器码和特征码的介绍与关系:https://www.cnblogs.com/qiumingcheng/p/5400265.html
在上面的函数中通过0x45A1D0比较OEP的机器码与特征码,提取出具有相同特性的编译器版本。
例如
这是OEP的部分数据
8B EC 6A FF F0 U嬱jh饊@.h@A@.d
A1 EC ?...Pd?....冹
E8 FF 0C D2 8A D4 SVW塭?.€@.3見?
6C BA 8B C8 E1 FF 0D ?l篅.嬋佱...?
BA C1 E1 CA 0D BA C1 h篅.玲蕢.d篅.?
使用数据拼接成机器码指令
0x55 0x8b 0xec 0x6a 0xff
0045A3E0 push ebp
0045A3E1 8BEC mov ebp,esp
0045A3E3 6A FF push -0x1
PEiD解析流程
- PEiD解析编译器的流程总结:
- 读取文件,分析出PE结构,保存。
- 检查OEP,修正OE,再次检查OEP
- 使用OEP处的机器码与特征码比较
- 通过比较结果匹配储存函数指针的数组中的过程,将下标存储到数组
- 检查文件是否存在rdata节
- 循环,从存储下标的数组中取出下标,调用对应的函数。
- 在处理函数中再次检查OEP的机器码与特征码
- 获取并显示编译器版本
开发环境伪造
在第一次文件判定中,我们知道会检测OEP是否在.text节中,因此,我们只需要将伪造OEP写入.text节后,使用HEX Editor改变原来OEP即可
8B EC 6A FF F0
A1 EC
E8 5F 5E 5B C4 A3
E8 FA FF FF
使用一个简单的Hello World程序进行伪造OEP
1.初始的OEP地址在0xF012C2处,写入伪造OEP数据
2.保存修改后的文件后,OD打开,起始偏移地址为1810
3.HEX Editor定位到偏移地址0x110处
将原OEP偏移地址0x12C2改为0x1810即可
本次实战复现主要是对程序特征码的识别,日后可以用于病毒程序,游戏外挂的识别判断。迟到了...wokao...
逆向与反汇编实战(一)--PEiD分析复现的更多相关文章
- Spring Boot 揭秘与实战 源码分析 - 工作原理剖析
文章目录 1. EnableAutoConfiguration 帮助我们做了什么 2. 配置参数类 – FreeMarkerProperties 3. 自动配置类 – FreeMarkerAutoCo ...
- Spring Boot 揭秘与实战 源码分析 - 开箱即用,内藏玄机
文章目录 1. 开箱即用,内藏玄机 2. 总结 3. 源代码 Spring Boot提供了很多”开箱即用“的依赖模块,那么,Spring Boot 如何巧妙的做到开箱即用,自动配置的呢? 开箱即用,内 ...
- Spring Boot 实战与原理分析视频课程
Spring Boot 实战与原理分析视频课程 链接:https://pan.baidu.com/share/init?surl=PeykcoeqZtd1d9lN9V_F-A 提取码: 关注公众号[G ...
- ThinkCMF X1.6.0-X2.2.3框架任意内容包含漏洞分析复现
ThinkCMF X1.6.0-X2.2.3框架任意内容包含漏洞分析复现 一.ThinkCMF简介 ThinkCMF是一款基于PHP+MYSQL开发的中文内容管理系统框架,底层采用ThinkPHP3. ...
- 黑龙江网络安全技能竞赛awd后门分析复现
0x0环境 0x1分析复现 0x2感想 围绕主办方留下的浅显后门可以打满整场,想拿第一还是要搞定深层后门
- CVE-2020-7245 CTFd v2.0.0 – v2.2.2漏洞分析复现
CVE-2020-7245 CTFd v2.0.0 – v2.2.2漏洞分析复现 一.漏洞介绍 在 CTFd v2.0.0 - v2.2.2 的注册过程中,如果知道用户名并在 CTFd 实例上启用 ...
- ThinkCMF框架任意内容包含漏洞分析复现(写入shell+文件包哈)
ThinkCMF框架任意内容包含漏洞分析复现 0x00 简介 ThinkCMF是一款基于PHP+MYSQL开发的中文内容管理框架,底层采用ThinkPHP3.2.3构建.ThinkCMF提出灵活的应用 ...
- 《ElasticSearch6.x实战教程》之实战ELK日志分析系统、多数据源同步
第十章-实战:ELK日志分析系统 ElasticSearch.Logstash.Kibana简称ELK系统,主要用于日志的收集与分析. 一个完整的大型分布式系统,会有很多与业务不相关的系统,其中日志系 ...
- Thinkcmf任意漏洞包含漏洞分析复现
简介 ThinkCMF是一款基于PHP+MYSQL开发的中文内容管理框架,底层采用ThinkPHP3.2.3构建.ThinkCMF提出灵活的应用机制,框架自身提供基础的管理功能,而开发者可以根据自身的 ...
随机推荐
- Card Game Cheater
Card Game Cheater Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- Springboot入门:
Springboot入门: 1.springboot是基于spring的全新框架,设计目的:简化spring应用配置和开发过程. 该框架遵循“约定大于配置”原则,采用特定的方式进行配置,从而事开发者无 ...
- 3-Gitblit服务器搭建及IDEA整合Git使用
背景:虽然有GitHub.GitLab这样强大的Git仓库,但是涉及私有Git库要收费,所以自己动手搭建免费的用用 环境:windows 7 旗舰版.JDK 1.8.IDEA 2017 ------- ...
- python中加入中文注释报错处理
python中加入中文注释,运行报错如下 解决方法: 在py文件的第一行加入 #coding:utf-8 即可
- 启动Maven项目时报错Failed to execute goal org.apache.maven.plugins:maven-clean-plugin:2.5:clean (default-clean) on project **-web: Failed to clean project: Failed to delete E:\**\target\tomcat\logs\access_lo
这类错误 出现这种错误,通常是由于您已启动了另一个tomcat 进程或者运行的javaw.exe进程,导致报错. 解决方法: 1. 鼠标点击 X 进行关闭运行失败的 Console页,(如果运行多次, ...
- 【Spark机器学习速成宝典】基础篇03数据读取与保存(Python版)
目录 保存为文本文件:saveAsTextFile 保存为json:saveAsTextFile 保存为SequenceFile:saveAsSequenceFile 读取hive 保存为文本文件:s ...
- Electron-Vue工程初始化,以及需要掌握的相关知识
1.安装nodejs 下载地址:http://nodejs.cn/ 需要重启系统 2.安装electron npm install electron -g 3.安装vue npm install vu ...
- C/C++判断字符串是否包含某个字符串
C风格 #include <iostream> #include <string> #include <cstring> using namespace std; ...
- ssm项目dao层方法异常:org.apache.ibatis.binding.BindingException: Invalid bound statement
在IntelliJ IDEA中用ssm框架搭建了一个demo项目,在执行到dao层方法时抛出这个异常: org.apache.ibatis.binding.BindingException: Inva ...
- Openstack_单元测试工具 tox
目录 目录 扩展阅读 Openstack 的单元测试工具 单元测试工具使用流程 tox toxini 参考文章 扩展阅读 Python Mock的入门 Openstack 的单元测试工具 unitte ...