闲来无事,随便逆逆。
首先编译器编译的时候会使用CraeteFileW创建源文件,这个断点我们可以OD打开一个编译器,直接对所有文件操作的函数下断就能断下来了。先看第一个,创建源文件:
代码:
0044F680 /$ 53 PUSH EBX 0044F681 |. 8B4424 08 MOV EAX,DWORD PTR SS:[ESP+8] 0044F685 |. 8B5C24 0C MOV EBX,DWORD PTR SS:[ESP+C] 0044F689 |. 6A 00 PUSH 0 ; /hTemplateFile = NULL 0044F68B |. 6A 00 PUSH 0 ; |Attributes = 0 0044F68D |. 6A 03 PUSH 3 ; |Mode = OPEN_EXISTING 0044F68F |. 6A 00 PUSH 0 ; |pSecurity = NULL 0044F691 |. 6A 01 PUSH 1 ; |ShareMode = FILE_SHARE_READ 0044F693 |. 68 00000080 PUSH 80000000 ; |Access = GENERIC_READ 0044F698 |. 50 PUSH EAX ; |目标源文件 0044F699 |. FF15 4CD05100 CALL DWORD PTR DS:[<&KERNEL32.CreateFileW>] ; \CreateFileW 0044F69F |. 8903 MOV DWORD PTR DS:[EBX],EAX ; 返回句柄 0044F6A1 |. 833B FF CMP DWORD PTR DS:[EBX],-1 ; 判断是否为空 0044F6A4 |. 75 08 JNZ SHORT 0044F6AE 0044F6A6 |. FF15 18CF5100 CALL DWORD PTR DS:[<&KERNEL32.GetLastError>] ; [GetLastError 0044F6AC |. EB 02 JMP SHORT 0044F6B0
CreateFile之后就ReadFile读取前4字节,前4字节一般就是#inc,然后比较这4字节是否等于0xFFFEFEFF,这个字符我们弄到十六进制编辑器里面会发现是空白,
代码:
0x0FEFF
代码:
00450168 |. 50 PUSH EAX ; /Arg1 00450169 |. E8 82F7FFFF CALL 0044F8F0 ; \再次获得文件大小 0045016E |. 85D2 TEST EDX,EDX 00450170 |. 72 10 JB SHORT 00450182 00450172 |. 77 07 JA SHORT 0045017B 00450174 |. 3D 00000080 CMP EAX,80000000 ; 原代码大小 00450179 |. 76 07 JBE SHORT 00450182 ; 小于等于这个数就跳 0045017B |> B8 05000020 MOV EAX,20000005 ; 不然设置EAX为这个数字,后返回 00450180 |. EB 57 JMP SHORT 004501D9
读取之后判断是否为UTF8编码,相关代码如下:
代码:
004B2A6B |. 56 PUSH ESI ; 原代码大小 004B2A6C |. 8B45 E4 MOV EAX,DWORD PTR SS:[EBP-1C] 004B2A6F |. 50 PUSH EAX ; 指向原代码内存的指针 004B2A70 |. FF15 F0D65100 CALL DWORD PTR DS:[<&support._IsEncodingUTF8>] ; support._IsEncodingUTF8
代码:
004B2DDA |> /46 /INC ESI ; ESI指向内存中的源代码字符, 004B2DDB |> |3B75 FC CMP ESI,DWORD PTR SS:[EBP-4] 004B2DDE |. |73 16 |JNB SHORT 004B2DF6 004B2DE0 |. |8A06 |MOV AL,BYTE PTR DS:[ESI] 004B2DE2 |. |3C 0A |CMP AL,0A 004B2DE4 |. |74 10 |JE SHORT 004B2DF6 ; 比较是否为换行,查找第一个换行或者第一个回车 004B2DE6 |. |3C 0D |CMP AL,0D 004B2DE8 |. |74 0C |JE SHORT 004B2DF6 ; 比较是否为回车 004B2DEA |. |89F0 |MOV EAX,ESI 004B2DEC |. |2B45 F8 |SUB EAX,DWORD PTR SS:[EBP-8] 004B2DEF |. |3D 00100000 |CMP EAX,1000 004B2DF4 |.^\7C E4 \JL SHORT 004B2DDA 004B2DF6 |> 3B75 F8 CMP ESI,DWORD PTR SS:[EBP-8] ; 查找到第一个换行或者回车之后就跳
代码:
004B2E04 |. 803E 0D CMP BYTE PTR DS:[ESI],0D ; 判断是否为回车 004B2E07 |. 75 0F JNZ SHORT 004B2E18 004B2E09 |. 807E 01 0A CMP BYTE PTR DS:[ESI+1],0A ; 换行 004B2E0D |. 75 09 JNZ SHORT 004B2E18 004B2E0F |. 834B 18 0C OR DWORD PTR DS:[EBX+18],0C 004B2E13 |. 83C6 02 ADD ESI,2 ; 是就字符+2
之后继续循环比较,从换行和回车后面开始比较。
这个过程就是检查头文件语法。因为#include <windows>这后面是回车换行,
上面这个过程转换为宽字符,其中还有些处理。剩下的。。。。