windows下的反汇编程序为何如此复杂
C源程序:
# include <stdio.h>
int global_x = 9;
void function(int a,int b)
{
}
int main()
{
int local_x = 5;
function(1,2);
return 0;
}
LINUX下反汇编:
(gdb) disas main
Dump of assembler code for function main:
0x080483c7 <+0>:push %ebp
0x080483c8 <+1>:mov %esp,%ebp
0x080483ca <+3>:sub $0x18,%esp
0x080483cd <+6>:movl $0x5,-0x4(%ebp)
0x080483d4 <+13>:movl $0x2,0x4(%esp)
0x080483dc <+21>:movl $0x1,(%esp)
0x080483e3 <+28>:call 0x80483b4 <function>
0x080483e8 <+33>:mov $0x0,%eax
0x080483ed <+38>:leave
0x080483ee <+39>:ret
End of assembler dump.
(gdb)
WINDOWS下反汇编:
CPU Disasm
地址 HEX 数据 指令 注释
00401190 /$ 55 PUSH EBP ; temp.<模块入口点> (void
00401191 |. 8BEC MOV EBP,ESP
00401193 |. 6A FF PUSH -1
00401195 |. 68 30214200 PUSH OFFSET 00422130
0040119A |. 68 40424000 PUSH __except_handler3
0040119F |. 64:A1 0000000 MOV EAX,DWORD PTR FS:[0]
004011A5 |. 50 PUSH EAX
004011A6 |. 64:8925 00000 MOV DWORD PTR FS:[0],ESP ; Installs SE 处理器 __except_handler3
004011AD |. 83C4 F0 ADD ESP,-10
004011B0 |. 53 PUSH EBX
004011B1 |. 56 PUSH ESI
004011B2 |. 57 PUSH EDI
004011B3 |. 8965 E8 MOV DWORD PTR SS:[LOCAL.6],ESP
004011B6 |. FF15 4CA14200 CALL DWORD PTR DS:[<&KERNEL32.GetVersion ; [KERNEL32.GetVersion
004011BC |. A3 847C4200 MOV DWORD PTR DS:[_osver],EAX
004011C1 |. A1 847C4200 MOV EAX,DWORD PTR DS:[_osver]
004011C6 |. C1E8 08 SHR EAX,8
004011C9 |. 25 FF000000 AND EAX,000000FF
004011CE |. A3 907C4200 MOV DWORD PTR DS:[_winminor],EAX
004011D3 |. 8B0D 847C4200 MOV ECX,DWORD PTR DS:[_osver]
004011D9 |. 81E1 FF000000 AND ECX,000000FF
004011DF |. 890D 8C7C4200 MOV DWORD PTR DS:[_winmajor],ECX
004011E5 |. 8B15 8C7C4200 MOV EDX,DWORD PTR DS:[_winmajor]
004011EB |. C1E2 08 SHL EDX,8
004011EE |. 0315 907C4200 ADD EDX,DWORD PTR DS:[_winminor]
004011F4 |. 8915 887C4200 MOV DWORD PTR DS:[_winver],EDX
004011FA |. A1 847C4200 MOV EAX,DWORD PTR DS:[_osver]
004011FF |. C1E8 10 SHR EAX,10
00401202 |. 25 FFFF0000 AND EAX,0000FFFF
00401207 |. A3 847C4200 MOV DWORD PTR DS:[_osver],EAX
0040120C |. 6A 00 PUSH 0
0040120E |. E8 BD2D0000 CALL _heap_init ; [_heap_init
00401213 |. 83C4 04 ADD ESP,4
00401216 |. 85C0 TEST EAX,EAX
00401218 |. 75 0A JNE SHORT 00401224
0040121A |. 6A 1C PUSH 1C
0040121C |. E8 CF000000 CALL fast_error_exit ; [fast_error_exit
00401221 |. 83C4 04 ADD ESP,4
00401224 |> C745 FC 00000 MOV DWORD PTR SS:[LOCAL.1],0
0040122B |. E8 A0270000 CALL _ioinit ; [_ioinit
00401230 |. FF15 48A14200 CALL DWORD PTR DS:[<&KERNEL32.GetCommand ; [KERNEL32.GetCommandLineA
00401236 |. A3 04964200 MOV DWORD PTR DS:[_acmdln],EAX
0040123B |. E8 70250000 CALL __crtGetEnvironmentStringsA ; [__crtGetEnvironmentStringsA
00401240 |. A3 5C7C4200 MOV DWORD PTR DS:[_aenvptr],EAX
00401245 |. E8 56200000 CALL _setargv ; [_setargv
0040124A |. E8 011F0000 CALL _setenvp ; [_setenvp
0040124F |. E8 1C1B0000 CALL _cinit ; [_cinit
00401254 |. 8B0D A07C4200 MOV ECX,DWORD PTR DS:[_environ]
0040125A |. 890D A47C4200 MOV DWORD PTR DS:[__initenv],ECX
00401260 |. 8B15 A07C4200 MOV EDX,DWORD PTR DS:[_environ]
00401266 |. 52 PUSH EDX
00401267 |. A1 987C4200 MOV EAX,DWORD PTR DS:[__argv]
0040126C |. 50 PUSH EAX
0040126D |. 8B0D 947C4200 MOV ECX,DWORD PTR DS:[__argc]
00401273 |. 51 PUSH ECX
00401274 |. E8 91FDFFFF CALL 0040100A ; [main
00401279 |. 83C4 0C ADD ESP,0C
0040127C |. 8945 E4 MOV DWORD PTR SS:[LOCAL.7],EAX
0040127F |. 8B55 E4 MOV EDX,DWORD PTR SS:[LOCAL.7]
00401282 |. 52 PUSH EDX
00401283 |. E8 281B0000 CALL exit ; [exit
00401288 |. 8B45 EC MOV EAX,DWORD PTR SS:[LOCAL.5]
0040128B |. 8B08 MOV ECX,DWORD PTR DS:[EAX]
0040128D |. 8B11 MOV EDX,DWORD PTR DS:[ECX]
0040128F |. 8955 E0 MOV DWORD PTR SS:[LOCAL.8],EDX
00401292 |. 8B45 EC MOV EAX,DWORD PTR SS:[LOCAL.5]
00401295 |. 50 PUSH EAX
00401296 |. 8B4D E0 MOV ECX,DWORD PTR SS:[LOCAL.8]
00401299 |. 51 PUSH ECX
0040129A |. E8 A11C0000 CALL _XcptFilter ; [_XcptFilter
0040129F |. 83C4 08 ADD ESP,8
004012A2 \. C3 RETN
对比来看,linux下的反汇编程序非常短小,windows下的则冗长复杂,比如下面几行00401193 |. 6A FF PUSH -1 ;有什么作用,虽然可以不理他。
004011BC |. A3 847C4200 MOV DWORD PTR DS:[_osver],EAX
004011C1 |. A1 847C4200 MOV EAX,DWORD PTR DS:[_osver] ;在搞笑么?
00401254 |. 8B0D A07C4200 MOV ECX,DWORD PTR DS:[_environ]
0040125A |. 890D A47C4200 MOV DWORD PTR DS:[__initenv],ECX
00401260 |. 8B15 A07C4200 MOV EDX,DWORD PTR DS:[_environ]
PUSH EAX ;只能根据相应的值去琢磨其功能,可读性太差
总体来讲,如果拿一个陌生的.exe进行反汇编,我根本看不懂这个程序的功能,但是在Linux下则可以一目了然。
最近自学习漏洞方面的,随时用到反汇编,看了一些教程,自己的反汇编代码或多或少都与教程中的反汇编代码有些差异,特别是windows下的反汇编,差别大,又读不懂。希望有朋友给点建议,接下来如何学习。
X86汇编,我有一些基础,学过这门课,但是只写一些小程序,没怎么练过。指令什么的都懂,但是那么一大堆汇编代码放在那里,看不懂是什么程序,现在正在艰难的学习中,有经验的朋友给些建议,感激不尽
[解决办法]
因为你 Windows 的那个看到的不是你代码所对应的部分,这部分 main() 应该是在 0040100A 处,function() 不出意外的话应该是在 00401000 处。你所看到的这些,是些初始化和预处理的内容,为程序部分提供个所预设的环境和条件,比如错误处理、命令行参数等等。
[解决办法]
WINDOWS下 程序初始化有一系列的动作~ GetVersion GetCommand 还有其他的~
004011BC
[解决办法]
. A3 847C4200 MOV DWORD PTR DS:[_osver],EAX
004011C1
[解决办法]
. A1 847C4200 MOV EAX,DWORD PTR DS:[_osver]
这个编译器为什么这样做我不知道。 我只知道它可以是一个 后门
[解决办法]
>> 为什么每个main函数中都要把EBX、EDI、ESI入栈呢 ...
这个不是 main() 函数特有的行为,而是所有的函数都这样。这涉及到对寄存器使用的个约定上,即规定在函数/子程中,可以随意使用 eax/edx/ecx 寄存器而无须进行保护和恢复操作,当然了,eax 有函数返回值的角色。而对 ebx/esi/edi 这三个寄存器,如果修改了,就需要对它们进行保护和恢复的操作以保证它们的内容在经过函数/子程后没有变化。
有些编译器,在某些优化上,会对没有使用到的 ebx/esi/edi 不进行保护和恢复,只针对使用到的进行;而有些出于代码简单和通用上的考虑,就不管是否用到都一股脑地进行保护和恢复。