00407C9C /$ B8 AC7C4000 mov eax, 00407CAC ;
00407CA1 |. E8 F2FFFFFF call 00407C98
本人是新手, 刚看到这两句真不知道是干什么的, 但是由于有些汇编和正向编程经验,所以
call 还是知道的, 步进了call 发现 将 eax传给了ebx, 后来又做了恢复。
可见eax 存储的应该是函数的参数, 但是由于汇编无类型,或者说大部分都是 几字节 双字
单字的, 这对于习惯高级语言的 实在痛苦。
到这里基本上停顿了, 后来就干脆试试 为任意一个函数仅有一个参数的进行反汇编,
任意的改变类型。 于是就得到下面的一堆片段, 本来我是想 反过大部分情况后 比如
Integer Boolean Char String PChar Real Single 等作为参数情况后然后再里面找的, 我还找了本官方的Object Pascal 来从头逐个对 各种 运算符 流程控制 函数 参数, 函数指针 类
集合 记录 等进行反 , 恩 忘了说, 我反的是Delphi写的。
00000000
..................
code. jmp 行1985
题目: Delphi 7 的反汇编结果, 编译选项默认。
0.不同的subsystem, 子系统编译出来的反汇编头结果。
当子系统为控制台时也就是{APPTYPE CONSOLE}时,
004034F0 > $ 55 push ebp
004034F1 . 8BEC mov ebp, esp
004034F3 . 83C4 F0 add esp, -10
004034F6 . A1 A0404000 mov eax, dword ptr [4040A0]
004034FB . C600 01 mov byte ptr [eax], 1
004034FE . B8 B8344000 mov eax, 004034B8
00403503 . E8 DCFDFFFF call 004032E4
00403508 . E8 CBFEFFFF call 004033D8 ; WinMain函数中转。名字无所谓。
0040350D . E8 EAF8FFFF call 00402DFC
//begin相当于{ end 相当于}
当子系统为GUI时也就是{APPTYPE GUI}时,Delphi 7的入口为:
004034F0 > $ 55 push ebp
004034F1 . 8BEC mov ebp, esp
004034F3 . 83C4 F0 add esp, -10
004034F6 . B8 B8344000 mov eax, 004034B8
004034FB . E8 E4FDFFFF call 004032E4
00403500 . E8 D3FEFFFF call 004033D8;
这里利用另外一个函数中转,是procedure,表示无返回值。
00403505 . E8 F2F8FFFF call 00402DFC
0040350A . 8BC0 mov eax, eax
无论是用procedure还是function并不影响入口头的编译指令。
004034F4 > $ 55 push ebp
004034F5 . 8BEC mov ebp, esp
004034F7 . 83C4 F0 add esp, -10
004034FA . B8 BC344000 mov eax, 004034BC
004034FF . E8 E0FDFFFF call 004032E4
00403504 . E8 CFFEFFFF call 004033D8
00403509 . E8 EEF8FFFF call 00402DFC
一、 函数, 函数参数, 指针类型, 类对象类型。
1. 对不同函数参数, 对不同Delphi过程的反汇编进行总结。
首先按四个参数进行, 四个参数的类型上进行逐一对比。
(1)四个参数全为Integer型
00403460 /$ 6A 04 push 4
00403462 |. B9 03000000 mov ecx, 3
00403467 |. BA 02000000 mov edx, 2
0040346C |. B8 01000000 mov eax, 1
00403471 |. E8 A2FFFFFF call 00403418
一个整型参数
0040345C /$ B8 01000000 mov eax, 1
00403461 |. E8 B2FFFFFF call 00403418
Cardinal类型时无变化, Cardinal是32位无符号整数
00403460 /$ 6A 05 push 5
00403462 |. B9 04000000 mov ecx, 4
00403467 |. BA 03000000 mov edx, 3
0040346C |. B8 0C000000 mov eax, 0C
00403471 |. E8 A2FFFFFF call 00403418
Shortint类型时,寄存使用8位的, 如 al dl
00403460 /$ 6A 05 push 5
00403462 |. B1 04 mov cl, 4
00403464 |. B2 03 mov dl, 3
00403466 |. B0 0C mov al, 0C
00403468 |. E8 ABFFFFFF call 00403418
Smallint类型时, 寄存器使用16位的, 如 ax, dx, 但是由于CPU默认一次传递最大是32位的,
所以不管处理什么最好默认类型都用32位的, 如果用小位的,则CPU要进行调整。
但是由于目前64位的CPU很多,当用64位操作系统时则最好使用64位的类型。
00403460 /$ 6A 05 push 5
00403462 |. 66:B9 0400 mov cx, 4
00403466 |. 66:BA 0300 mov dx, 3
0040346A |. 66:B8 0C00 mov ax, 0C
0040346E |. E8 A5FFFFFF call 00403418
Longint类型,为32位, 如eax, edx, ecx
00403460 /$ 6A 05 push 5
00403462 |. B9 04000000 mov ecx, 4
00403467 |. BA 03000000 mov edx, 3
0040346C |. B8 0C000000 mov eax, 0C
00403471 |. E8 A2FFFFFF call 00403418
使用64位Int64,则全变成了即时数,不再用寄存器中转
00403460 /$ 6A 00 push 0
00403462 |. 6A 0C push 0C
00403464 |. 6A 00 push 0
00403466 |. 6A 03 push 3
00403468 |. 6A 00 push 0
0040346A |. 6A 04 push 4
0040346C |. 6A 00 push 0
0040346E |. 6A 05 push 5
00403470 |. E8 A3FFFFFF call 00403418
使用8位的Byte, 则还为8位的al
00403460 /$ 6A 05 push 5
00403462 |. B1 04 mov cl, 4
00403464 |. B2 03 mov dl, 3
00403466 |. B0 0C mov al, 0C
00403468 |. E8 ABFFFFFF call 00403418
使用16位的Word, 则为16位的ax
00403460 /$ 6A 05 push 5
00403462 |. 66:B9 0400 mov cx, 4
00403466 |. 66:BA 0300 mov dx, 3
0040346A |. 66:B8 0C00 mov ax, 0C
0040346E |. E8 A5FFFFFF call 00403418
使用32位的Longword, 则为32位的eax
00403460 /$ 6A 05 push 5
00403462 |. B9 04000000 mov ecx, 4
00403467 |. BA 03000000 mov edx, 3
0040346C |. B8 0C000000 mov eax, 0C
00403471 |. E8 A2FFFFFF call 00403418
[结论] 四个参数大部分使用寄存器转参数
(2)四个参数全为字符型Char, 由于单个字符是8位,所以寄存器使用al dl cl作中转。
00403460 /$ 6A 33 push 33
00403462 |. B1 33 mov cl, 33
00403464 |. B2 32 mov dl, 32
00403466 |. B0 31 mov al, 31
00403468 |. E8 ABFFFFFF call 00403418
[结论] 四个参数大部分使用寄存器转参数, 不push, 或不每个参数都push.
(3)四个参数全为布尔值时, 序列为 True, False, True, False
00403460 /$ 6A 00 push 0
00403462 |. B1 01 mov cl, 1
00403464 |. 33D2 xor edx, edx
00403466 |. B0 01 mov al, 1
00403468 |. E8 ABFFFFFF call 00403418
序列为 True, True, True, True
00403460 /$ 6A 01 push 1
00403462 |. B1 01 mov cl, 1
00403464 |. B2 01 mov dl, 1
00403466 |. B0 01 mov al, 1
序列为 False, False, False, False时
00403460 /$ 6A 00 push 0
00403462 |. 33C9 xor ecx, ecx
00403464 |. 33D2 xor edx, edx
00403466 |. 33C0 xor eax, eax
00403468 |. E8 ABFFFFFF call 00403418, 由于 xor指令对相同则 = 0, 不同则为1。和
and指令相反, and 是 1 and 1 = 1 1 and 0 = 0, 0 and 1 = 0 0 and 0 = 0.
序列为 True, True, False, False时
00403460 /$ 6A 00 push 0
00403462 |. 33C9 xor ecx, ecx
00403464 |. B2 01 mov dl, 1
00403466 |. B0 01 mov al, 1
00403468 |. E8 ABFFFFFF call 00403418
序列为 False, False, True, True时
00403460 /$ 6A 01 push 1
00403462 |. B1 01 mov cl, 1
00403464 |. 33D2 xor edx, edx = 0
00403466 |. 33C0 xor eax, eax = 0
00403468 |. E8 ABFFFFFF call 00403418
(4)四个参数全为Real48的实数类型时, 全利用push 压入
0040343C /$ 68 852B0000 push 2B85
00403441 |. 68 8152B81E push 1EB85281(每个立即数占用48位)
00403446 |. 68 1E250000 push 251E
0040344B |. 68 81EC51B8 push B851EC81
00403450 |. 68 707D0000 push 7D70
00403455 |. 68 810AD7A3 push A3D70A81
0040345A |. 68 D7630000 push 63D7
0040345F |. 68 81713D0A push 0A3D7181
00403464 |. E8 8BFFFFFF call 004033F4
(5)四个参数全为Single的实数类型时, 仍然是全利用 push压入
0040343C /$ 68 1F85AB3F push 3FAB851F(每个占用32位)
00403441 |. 68 B81EA53F push 3FA51EB8
00403446 |. 68 A470FD3F push 3FFD70A4
0040344B |. 68 0AD7E33F push 3FE3D70A
00403450 |. E8 9FFFFFFF call 004033F4
(6)四个参数全为Double的实数类型时, Double是64位的,所以没个立即数占64位。
0040343C /$ 68 A370F53F push 3FF570A3
00403441 |. 68 713D0AD7 push D70A3D71
00403446 |. 68 D7A3F43F push 3FF4A3D7
0040344B |. 68 A4703D0A push 0A3D70A4
00403450 |. 68 14AEFF3F push 3FFFAE14
00403455 |. 68 AE47E17A push 7AE147AE
0040345A |. 68 E17AFC3F push 3FFC7AE1
0040345F |. 68 7B14AE47 push 47AE147B
00403464 |. E8 8BFFFFFF call 004033F4
(7)四个参数全为Extended的实数类型时, Extended是80位, 即立即数占80位。
0040343C /$ 68 FF3F0000 push 3FFF
00403441 |. 68 B81E85AB push AB851EB8
00403446 |. 68 1F85EB51 push 51EB851F
0040344B |. 68 FF3F0000 push 3FFF
00403450 |. 68 51B81EA5 push A51EB851
00403455 |. 68 B81E85EB push EB851EB8
0040345A |. 68 FF3F0000 push 3FFF
0040345F |. 68 D7A370FD push FD70A3D7
00403464 |. 68 A4703D0A push 0A3D70A4
00403469 |. 68 FF3F0000 push 3FFF
0040346E |. 68 3D0AD7E3 push E3D70A3D
00403473 |. 68 0AD7A370 push 70A3D70A
00403478 |. E8 77FFFFFF call 004033F4
(8)四个全为Comp
0040343C /$ 6A 00 push 0
0040343E |. 6A 01 push 1
00403440 |. 6A 00 push 0
00403442 |. 6A 01 push 1
00403444 |. 6A 00 push 0
00403446 |. 6A 02 push 2
00403448 |. 6A 00 push 0
0040344A |. 6A 02 push 2
0040344C |. E8 A3FFFFFF call 004033F4
(9)四个全为Currency类型的实数
0040343C /$ 6A 00 push 0
0040343E |. 68 58340000 push 3458
00403443 |. 6A 00 push 0
00403445 |. 68 64320000 push 3264
0040344A |. 6A 00 push 0
0040344C |. 68 584D0000 push 4D58
00403451 |. 6A 00 push 0
00403453 |. 68 88450000 push 4588
00403458 |. E8 97FFFFFF call 004033F4
(10)四个全为String字符串时的
0040345C /$ 68 80344000 push 00403480 ; ASCII "Hello"
00403461 |. B9 80344000 mov ecx, 00403480 ; ASCII "Hello"
00403466 |. BA 80344000 mov edx, 00403480 ; ASCII "Hello"
0040346B |. B8 80344000 mov eax, 00403480 ; ASCII "Hello"
00403470 |. E8 8FFFFFFF call 00403404
仍然是用寄存器传递
(11)四个全为WideString字符串时
0040349C /$ 68 BC344000 push 004034BC ; UNICODE "Hello"
004034A1 |. B9 BC344000 mov ecx, 004034BC ; UNICODE "Hello"
004034A6 |. BA BC344000 mov edx, 004034BC ; UNICODE "Hello"
004034AB |. B8 BC344000 mov eax, 004034BC ; UNICODE "Hello"
004034B0 |. E8 8FFFFFFF call 00403444
(12)四个全为PChar时
0040343C /$ 68 58344000 push 00403458 ; ASCII "Hello"
00403441 |. B9 58344000 mov ecx, 00403458 ; ASCII "Hello"
00403446 |. BA 58344000 mov edx, 00403458 ; ASCII "Hello"
0040344B |. B8 58344000 mov eax, 00403458 ; ASCII "Hello"
00403450 |. E8 9FFFFFFF call 004033F4
二、 赋值情况, 算术, 过程, 函数, 流程控制, 循环, 其他语句,数组。
1. 当给一个字符串string类型在函数过程中赋值时,
004033DF |. A1 A0404000 mov eax, dword ptr [4040A0]
004033E4 |. E8 9BFBFFFF call 00402F84 //赋值我们很理解,
//但是加一个处理就很纳闷了,可能是Delphi特有的,但是这样我们就可以知道,究竟哪里是Delphi多出的部分了。
b := 90;
a := IntToStr(12);
MessageBox(0, PChar(a), PChar(a), 0);
对上面进行反汇编, 产生熟悉的情形, 增加了push ebp, 保存基地址。
其中 00402F84步入后呈现为:
00402F84 /$ 85C0 test eax, eax ; heloMain.004033D0
00402F86 |. 74 02 je short 00402F8A
00402F88 |. C3 retn
返回值不同类型的状态
(1)返回值为Integer时
00407C74 /$ 33C0 xor eax, eax
00407C76 \. C3 retn
当使用Writeln(100)时
004081B8 |. A1 04934000 mov eax, dword ptr [409304]
004081BD |. BA 64000000 mov edx, 64 //edx = 100
004081C2 |. E8 0DABFFFF call 00402CD4
004081C7 |. E8 38ABFFFF call 00402D04
004081CC |. E8 5BA4FFFF call 0040262C
全局变量赋值 , 整数。
00407C68 |. C705 94824000>mov dword ptr [408294], 0C8
局部变量是在变量被引用的时候才赋值,不引用则不赋值。
004081B0 /$ 53 push ebx
004081B9 |. BB AA000000 mov ebx, 0AA ;单个一个Integer时就使用个寄存器
;所以要push ebx一下以ret后恢复
004081BE |. A1 04934000 mov eax, dword ptr [409304]
004081C3 |. 8BD3 mov edx, ebx
004081C5 |. E8 0AABFFFF call 00402CD4
004081CA |. E8 35ABFFFF call 00402D04
004081CF |. E8 58A4FFFF call 0040262C
//当要输出的数是一个变量时。
004081B8 |. A1 08934000 mov eax, dword ptr [409308]
004081BD |. 8B15 98924000 mov edx, dword ptr [409298]
004081C3 |. E8 0CABFFFF call 00402CD4
004081C8 |. E8 37ABFFFF call 00402D04
004081CD |. E8 5AA4FFFF call 0040262C
当两个Writeln(<变量>)时候
004081B9 |. BB AA000000 mov ebx, 0AA
004081BE |. A1 08934000 mov eax, dword ptr [409308]
004081C3 |. 8BD3 mov edx, ebx
004081C5 |. E8 0AABFFFF call 00402CD4
004081CA |. E8 35ABFFFF call 00402D04
004081CF |. E8 58A4FFFF call 0040262C
004081D4 |. A1 08934000 mov eax, dword ptr [409308]
004081D9 |. 8B15 98924000 mov edx, dword ptr [409298]
004081DF |. E8 F0AAFFFF call 00402CD4
004081E4 |. E8 1BABFFFF call 00402D04
004081E9 |. E8 3EA4FFFF call 0040262C
可见, Writeln(是靠 mov edx, ebx来控制, 而 mov eax, dword ptr [409308]总是存在
三次call是必须的。
当为Writeln(#89)时
0040808C |. A1 04934000 mov eax, dword ptr [409304]
00408091 |. B2 59 mov dl, 59
00408093 |. E8 04ABFFFF call 00402B9C
00408098 |. E8 3BABFFFF call 00402BD8
0040809D |. E8 8AA5FFFF call 0040262C
单个一个变量赋值 Size := 400; ,变量为全局
00407C68 |. C705 94824000>mov dword ptr [408294], 190
单个一个指针类型的变量 根据 立即数可以发现 00408294是个地址。所以还是有区别的。
nSize := @Size;
00407C68 |. C705 9C974000>mov dword ptr [40979C], 00408294
两个整数变量相加 rel := Size + pSize;
00407C68 |. A1 94824000 mov eax, dword ptr [408294], [408294]存储器操作数,
00407C6D |. 0305 98824000 add eax, dword ptr [408298]
00407C73 |. A3 9C824000 mov dword ptr [40829C], eax
除了特殊情况, 对一个变量的操作基本上都是存储器操作数。
两个整数变量相乘 rel := Size * pSize;
00407C68 |. A1 94824000 mov eax, dword ptr [408294]
00407C6D |. F72D 98824000 imul dword ptr [408298]
00407C73 |. A3 9C824000 mov dword ptr [40829C], eax
对一个整数变量进行取反, 是先取到一个eax里, 然后对eax取反。
00407C68 |. A1 94824000 mov eax, dword ptr [408294]
00407C6D |. F7D0 not eax
00407C6F |. A3 98824000 mov dword ptr [408298], eax
对一个Boolean的进行not, tBool := not tBool;
00407C68 |. A0 94824000 mov al, byte ptr [408294]
00407C6D |. 34 01 xor al, 1
00407C6F |. A2 94824000 mov byte ptr [408294], al
两个整数相减, sub指令。
00407C68 |. A1 94824000 mov eax, dword ptr [408294]
00407C6D |. 2B05 98824000 sub eax, dword ptr [408298]
00407C73 |. A3 9C824000 mov dword ptr [40829C], eax
两个浮点数进行相加
tReal := 12.2;
bReal := tReal + 0.5;
tReal := tReal + bReal;
00407C68 |. C705 9C974000>mov dword ptr [40979C], 66666666
00407C72 |. C705 A0974000>mov dword ptr [4097A0], 40286666
00407C7C |. DD05 9C974000 fld qword ptr [40979C]
00407C82 |. D805 B07C4000 fadd dword ptr [407CB0]
00407C88 |. DD1D A4974000 fstp qword ptr [4097A4]
00407C8E |. 9B wait
00407C8F |. DD05 9C974000 fld qword ptr [40979C]
00407C95 |. DC05 A4974000 fadd qword ptr [4097A4]
00407C9B |. DD1D 9C974000 fstp qword ptr [40979C]
00407CA1 |. 9B wait
两个浮点进行相除
00407C68 |. DB05 94824000 fild dword ptr [408294]
00407C6E |. DB05 98824000 fild dword ptr [408298]
00407C74 |. DEF9 fdivp st(1), st
00407C76 |. DD1D 9C974000 fstp qword ptr [40979C]
00407C7C |. 9B wait
两个浮点进行整除 tReal := Size div pSize; 取整。
00407C69 |. A1 94824000 mov eax, dword ptr [408294]
00407C6E |. 99 cdq
00407C6F |. F73D 98824000 idiv dword ptr [408298]
00407C75 |. 890424 mov dword ptr [esp], eax //eax存储商
00407C78 |. DB0424 fild dword ptr [esp] //装入整数
00407C7B |. DD1D 9C974000 fstp qword ptr [40979C]
00407C81 |. 9B wait
两个浮点进行取余
00407C69 |. A1 94824000 mov eax, dword ptr [408294]
00407C6E |. 99 cdq
00407C6F |. F73D 98824000 idiv dword ptr [408298]
00407C75 |. 891424 mov dword ptr [esp], edx // edx存储余数
00407C78 |. DB0424 fild dword ptr [esp]
00407C7B |. DD1D 9C974000 fstp qword ptr [40979C]
00407C81 |. 9B wait
对一个整数进行取反
00407C68 |. F71D 94824000 neg dword ptr [408294]
对两个Boolean进行逻辑与 and
00407C68 |. 803D 94824000>cmp byte ptr [408294], 0
00407C6F |. 74 09 je short 00407C7A
00407C71 |. 803D 98824000>cmp byte ptr [408298], 0
00407C78 |. 75 04 jnz short 00407C7E
00407C7A |> 33C0 xor eax, eax
00407C7C |. EB 02 jmp short 00407C80
00407C7E |> B0 01 mov al, 1
00407C80 |> A2 94824000 mov byte ptr [408294], al
为两Boolean赋真值和假值
00407C68 |. C605 94824000>mov byte ptr [408294], 1 , 真
00407C6F |. C605 98824000>mov byte ptr [408298], 0 , 假
进行逻辑与后再存储在Boolean变量中
00407C68 |. C605 94824000>mov byte ptr [408294], 1
00407C6F |. C605 98824000>mov byte ptr [408298], 0
00407C76 |. 803D 94824000>cmp byte ptr [408294], 0
00407C7D |. 74 09 je short 00407C88
00407C7F |. 803D 98824000>cmp byte ptr [408298], 0
00407C86 |. 75 04 jnz short 00407C8C
00407C88 |> 33C0 xor eax, eax
00407C8A |. EB 02 jmp short 00407C8E
00407C8C |> B0 01 mov al, 1
00407C8E |> A2 9C974000 mov byte ptr [40979C], al
进行逻辑或
00407C68 |. C605 94824000>mov byte ptr [408294], 1
00407C6F |. C605 98824000>mov byte ptr [408298], 0
00407C76 |. 803D 94824000>cmp byte ptr [408294], 0
00407C7D |. 75 0D jnz short 00407C8C
00407C7F |. 803D 98824000>cmp byte ptr [408298], 0
00407C86 |. 75 04 jnz short 00407C8C
00407C88 |. 33C0 xor eax, eax
00407C8A |. EB 02 jmp short 00407C8E
00407C8C |> B0 01 mov al, 1
00407C8E |> A2 9C974000 mov byte ptr [40979C], al
进行逻辑异或
00407C68 |. C605 94824000>mov byte ptr [408294], 1
00407C6F |. C605 98824000>mov byte ptr [408298], 0
00407C76 |. A0 94824000 mov al, byte ptr [408294] 只对是真的进行处理,另外逻辑运算都进行转换到Byte - 8bit
00407C7B |. 3205 98824000 xor al, byte ptr [408298]
00407C81 |. A2 9C974000 mov byte ptr [40979C], al
对整数则为位运算,这容易让人混淆。Size := not Size;
00407C68 |. F715 94824000 not dword ptr [408294]
对整数进行位运算与
00407C68 |. A1 94824000 mov eax, dword ptr [408294]
00407C6D |. 2305 98824000 and eax, dword ptr [408298]
00407C73 |. A3 9C824000 mov dword ptr [40829C], eax
00407C78 |. 89C0 mov eax, eax
对整数进行位运算或
00407C68 |. A1 94824000 mov eax, dword ptr [408294]
00407C6D |. 0B05 98824000 or eax, dword ptr [408298] //整数的比Boolean的容易看,
//使用与或非 异或指令很明显。
00407C73 |. A3 9C824000 mov dword ptr [40829C], eax
对整数进行位运算异或
00407C68 |. A1 94824000 mov eax, dword ptr [408294]
00407C6D |. 3305 98824000 xor eax, dword ptr [408298]
00407C73 |. A3 9C824000 mov dword ptr [40829C], eax
对整数进行位运算左移位 shl
00407C68 |. 8B0D 98824000 mov ecx, dword ptr [408298]
00407C6E |. A1 94824000 mov eax, dword ptr [408294]
00407C73 |. D3E0 shl eax, cl
00407C75 |. A3 9C824000 mov dword ptr [40829C], eax
对整数进行位运算右移位 shr
00407C68 |. 8B0D 98824000 mov ecx, dword ptr [408298]
00407C6E |. A1 94824000 mov eax, dword ptr [408294]
00407C73 |. D3E8 shr eax, cl
00407C75 |. A3 9C824000 mov dword ptr [40829C], eax
进行条件判断 = 时
[源]
if Size = 100 then
Writeln('Hello World');
004080F4 |. 833D 98924000>cmp dword ptr [409298], 64
004080FB |. 75 19 jnz short 00408116
004080FD |. A1 08934000 mov eax, dword ptr [409308]
00408102 |. BA 2C814000 mov edx, 0040812C ; ASCII "Hello World"
关系运算符 <> 时
if Size <> 100 then
begin
Writeln('Hello World');
end;
004080F4 |. 833D 98924000>cmp dword ptr [409298], 64
004080FB |. 74 19 je short 00408116 (ZF = 1)时
004080FD |. A1 08934000 mov eax, dword ptr [409308]
00408102 |. BA 2C814000 mov edx, 0040812C ; ASCII "Hello World"
00408107 |. E8 48BDFFFF call 00403E54
0040810C |. E8 07ABFFFF call 00402C18
00408111 |. E8 16A5FFFF call 0040262C
关系运算 < 时
if Size < 100 then
begin
Writeln('Hello World');
end;
004080F4 |. 833D 98924000>cmp dword ptr [409298], 64
004080FB |. 7D 19 jge short 00408116
004080FD |. A1 08934000 mov eax, dword ptr [409308]
00408102 |. BA 2C814000 mov edx, 0040812C ; ASCII "Hello World"
00408107 |. E8 48BDFFFF call 00403E54
0040810C |. E8 07ABFFFF call 00402C18
00408111 |. E8 16A5FFFF call 0040262C
关系运算 > 时
if Size > 100 then
begin
Writeln('Hello World');
end;
004080F4 |. 833D 98924000>cmp dword ptr [409298], 64
004080FB |. 7E 19 jle short 00408116
004080FD |. A1 08934000 mov eax, dword ptr [409308]
00408102 |. BA 2C814000 mov edx, 0040812C ; ASCII "Hello World"
00408107 |. E8 48BDFFFF call 00403E54
0040810C |. E8 07ABFFFF call 00402C18
00408111 |. E8 16A5FFFF call 0040262C
关系运算 <= 时
004080F4 |. 833D 98924000>cmp dword ptr [409298], 64
004080FB |. 7F 19 jg short 00408116
004080FD |. A1 08934000 mov eax, dword ptr [409308]
00408102 |. BA 2C814000 mov edx, 0040812C ; ASCII "Hello World"
00408107 |. E8 48BDFFFF call 00403E54
0040810C |. E8 07ABFFFF call 00402C18
00408111 |. E8 16A5FFFF call 0040262C
[源]
if Size <= 100 then
begin
Writeln('Hello World');
end;
关系运算 >= 时
004080F4 |. 833D 98924000>cmp dword ptr [409298], 64
004080FB |. 7C 19 jl short 00408116
004080FD |. A1 08934000 mov eax, dword ptr [409308]
00408102 |. BA 2C814000 mov edx, 0040812C ; ASCII "Hello World"
00408107 |. E8 48BDFFFF call 00403E54
0040810C |. E8 07ABFFFF call 00402C18
00408111 |. E8 16A5FFFF call 0040262C
[源]
if Size >= 100 then
begin
Writeln('Hello World');
end;
对单个字符取地址,并递增
00407C68 |. C705 9C974000>mov dword ptr [40979C], 00408294
00407C72 |. FF05 9C974000 inc dword ptr [40979C]
[源]
szcChar := @ccc;
szcChar := szcChar + 1;
取回原指针指向的内容
00407C68 |. C705 9C974000>mov dword ptr [40979C], 00408294
00407C72 |. A1 9C974000 mov eax, dword ptr [40979C]
00407C77 |. A3 9C974000 mov dword ptr [40979C], eax
00407C7C |. A1 9C974000 mov eax, dword ptr [40979C]
00407C81 |. 8A00 mov al, byte ptr [eax] //由于是字符指针,所以是byte(8)
00407C83 |. A2 98824000 mov byte ptr [408298], al
[源]
szcChar := @ccc;
szcChar := szcChar;
ccb := szcChar^; //取内容
不同赋值类型的反汇编。
整数
00407C68 |. C705 94824000>mov dword ptr [408294], 11D7
[源]
rel := 4567;
字符, 布尔, 浮点,
00407C68 |. C605 94824000>mov byte ptr [408294], 1
00407C6F |. C605 98824000>mov byte ptr [408298], 34
00407C76 |. C705 9C974000>mov dword ptr [40979C], CCCCCCCD //0.
00407C80 |. C705 A0974000>mov dword ptr [4097A0], 3FDCCCCC //45
[源]
tBool:= True;
ccc := '4';
tReal:= 0.45;
为一个字符串赋值
00407C68 |. B8 9C974000 mov eax, 0040979C
00407C6D |. BA 8C7C4000 mov edx, 00407C8C ; ASCII "Hello World"
00407C72 |. E8 D1B9FFFF call 00403648//调用此函数是在为字符传赋值.
为字符传赋值要使用两个地址。
批量对string进行赋值并没有变化指令
00407C8C |. B8 94824000 mov eax, 00408294 ;要填充的字符串变量地址
00407C91 |. BA CC7C4000 mov edx, 00407CCC ; ASCII "Hello World"
00407C96 |. E8 ADB9FFFF call 00403648
00407C9B |. B8 98824000 mov eax, 00408298
00407CA0 |. BA E07C4000 mov edx, 00407CE0 ; ASCII "Beijing"
00407CA5 |. E8 9EB9FFFF call 00403648
00407CAA |. B8 9C824000 mov eax, 0040829C
00407CAF |. BA F07C4000 mov edx, 00407CF0 ; ASCII "GuNiang"
00407CB4 |. E8 8FB9FFFF call 00403648
[源]
szStrN := 'Hello World';
szStrA := 'Beijing';
szStrZ := 'GuNiang';
拼接两个字符串
00407D00 |. B8 94824000 mov eax, 00408294
00407D05 |. BA 487D4000 mov edx, 00407D48 ; ASCII "Hello World"
00407D0A |. E8 39B9FFFF call 00403648
00407D0F |. B8 98824000 mov eax, 00408298
00407D14 |. BA 5C7D4000 mov edx, 00407D5C ; ASCII "Beijing"
00407D19 |. E8 2AB9FFFF call 00403648
00407D1E |. B8 9C824000 mov eax, 0040829C
00407D23 |. 8B0D 98824000 mov ecx, dword ptr [408298] ; heloMain.00407CE8
00407D29 |. 8B15 94824000 mov edx, dword ptr [408294] ; heloMain.00407CDC
00407D2F |. E8 80BBFFFF call 004038B4
[源]
szStrN := 'Hello World';
szStrA := 'Beijing';
szStrZ := szStrN + szStrA;
(2)二 第二部分 流程控制, 循环, 对象, 类型, 结构等。
条件分支语句, if .... then
00408118 |. 833D 98924000>cmp dword ptr [409298], 0
0040811F |. 74 19 je short 0040813A
00408121 |. A1 14934000 mov eax, dword ptr [409314]
00408126 |. BA 50814000 mov edx, 00408150 ; ASCII "Hello World"
0040812B |. E8 24BDFFFF call 00403E54
00408130 |. E8 E3AAFFFF call 00402C18
00408135 |. E8 F2A4FFFF call 0040262C
[源]
if rel <> 0 then
begin
Writeln('Hello World');
end;
条件分支语句, if ... then ... else
00408118 |. 833D 98924000>cmp dword ptr [409298], 0
0040811F |. 74 1B je short 0040813C
00408121 |. A1 14934000 mov eax, dword ptr [409314]
00408126 |. BA 68814000 mov edx, 00408168 ; ASCII "Hello World"
0040812B |. E8 24BDFFFF call 00403E54
00408130 |. E8 E3AAFFFF call 00402C18
00408135 |. E8 F2A4FFFF call 0040262C
0040813A |. EB 19 jmp short 00408155
0040813C |> A1 14934000 mov eax, dword ptr [409314]
00408141 |. BA 68814000 mov edx, 00408168 ; ASCII "Hello World"
00408146 |. E8 09BDFFFF call 00403E54
0040814B |. E8 C8AAFFFF call 00402C18
00408150 |. E8 D7A4FFFF call 0040262C
[源]
if rel <> 0 then
begin
Writeln('Hello World');
end
else
begin
Writeln('Hello World');
end;
条件分支语句 if ... then ... else if then .... else
00408118 |. 833D 98924000>cmp dword ptr [409298], 0
0040811F |. 74 1B je short 0040813C
00408121 |. A1 14934000 mov eax, dword ptr [409314]
00408126 |. BA 8C814000 mov edx, 0040818C ; ASCII "Hello World"
0040812B |. E8 24BDFFFF call 00403E54
00408130 |. E8 E3AAFFFF call 00402C18
00408135 |. E8 F2A4FFFF call 0040262C
0040813A |. EB 3D jmp short 00408179
0040813C |> 833D 98924000>cmp dword ptr [409298], 0
00408143 |. 75 1B jnz short 00408160
00408145 |. A1 14934000 mov eax, dword ptr [409314]
0040814A |. BA 8C814000 mov edx, 0040818C ; ASCII "Hello World"
0040814F |. E8 00BDFFFF call 00403E54
00408154 |. E8 BFAAFFFF call 00402C18
00408159 |. E8 CEA4FFFF call 0040262C
0040815E |. EB 19 jmp short 00408179
00408160 |> A1 14934000 mov eax, dword ptr [409314]
00408165 |. BA 8C814000 mov edx, 0040818C ; ASCII "Hello World"
0040816A |. E8 E5BCFFFF call 00403E54
0040816F |. E8 A4AAFFFF call 00402C18
00408174 |. E8 B3A4FFFF call 0040262C
[源]
if rel <> 0 then
begin
Writeln('Hello World');
end
else if rel = 0 then
begin
Writeln('Hello World');
end
else
begin
Writeln('Hello World');
end;
多分支语句 case .... of .... end;
00407C8C |. A1 94824000 mov eax, dword ptr [408294]
00407C91 |. 83E8 01 sub eax, 1 ; Switch (cases 0..1)
00407C94 |. 72 04 jb short 00407C9A
00407C96 |. 74 17 je short 00407CAF
00407C98 |. EB 28 jmp short 00407CC2
00407C9A |> 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL; Case 0 of switch 00407C91
00407C9C |. 68 D07C4000 push 00407CD0 ; |Title = "ggg"
00407CA1 |. 68 D47C4000 push 00407CD4 ; |Text = "0000"
00407CA6 |. 6A 00 push 0 ; |hOwner = NULL
00407CA8 |. E8 BBC8FFFF call <jmp.&user32.MessageBoxA> ; \MessageBoxA
00407CAD |. EB 13 jmp short 00407CC2
00407CAF |> 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL; Case 1 of switch 00407C91
00407CB1 |. 68 D07C4000 push 00407CD0 ; |Title = "ggg"
00407CB6 |. 68 DC7C4000 push 00407CDC ; |Text = "8899"
00407CBB |. 6A 00 push 0 ; |hOwner = NULL
00407CBD |. E8 A6C8FFFF call <jmp.&user32.MessageBoxA> ; \MessageBoxA
[源]
case Size of
0:
MessageBox(0, '0000', 'ggg', 0);
1:
MessageBox(0, '8899', 'ggg', 0);
end;
对多分支加了一个else
00407C8C |. A1 94824000 mov eax, dword ptr [408294]
00407C91 |. 83E8 01 sub eax, 1 ; Switch (cases 0..1)
00407C94 |. 72 04 jb short 00407C9A
00407C96 |. 74 17 je short 00407CAF
00407C98 |. EB 2A jmp short 00407CC4
00407C9A |> 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL; Case 0 of switch 00407C91
00407C9C |. 68 E47C4000 push 00407CE4 ; |Title = "ggg"
00407CA1 |. 68 E87C4000 push 00407CE8 ; |Text = "0000"
00407CA6 |. 6A 00 push 0 ; |hOwner = NULL
00407CA8 |. E8 BBC8FFFF call <jmp.&user32.MessageBoxA> ; \MessageBoxA
00407CAD |. EB 28 jmp short 00407CD7
00407CAF |> 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL; Case 1 of switch 00407C91
00407CB1 |. 68 E47C4000 push 00407CE4 ; |Title = "ggg"
00407CB6 |. 68 F07C4000 push 00407CF0 ; |Text = "8899"
00407CBB |. 6A 00 push 0 ; |hOwner = NULL
00407CBD |. E8 A6C8FFFF call <jmp.&user32.MessageBoxA> ; \MessageBoxA
00407CC2 |. EB 13 jmp short 00407CD7
00407CC4 |> 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL; Default case of switch 00407C91
00407CC6 |. 68 E47C4000 push 00407CE4 ; |Title = "ggg"
00407CCB |. 68 F87C4000 push 00407CF8 ; |Text = "78No"
00407CD0 |. 6A 00 push 0 ; |hOwner = NULL
00407CD2 |. E8 91C8FFFF call <jmp.&user32.MessageBoxA> ; \MessageBoxA
[源]
case Size of
0:
MessageBox(0, '0000', 'ggg', 0);
1:
MessageBox(0, '8899', 'ggg', 0);
else
MessageBox(0, '78No', 'ggg', 0);
end;
多分支加了 case = 2
00407C8C |. A1 94824000 mov eax, dword ptr [408294]
00407C91 |. 83E8 01 sub eax, 1 ; Switch (cases 0..2)
00407C94 |. 72 07 jb short 00407C9D
00407C96 |. 74 1A je short 00407CB2
00407C98 |. 48 dec eax
00407C99 |. 74 2C je short 00407CC7
00407C9B |. EB 3F jmp short 00407CDC
00407C9D |> 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL; Case 0 of switch 00407C91
00407C9F |. 68 FC7C4000 push 00407CFC ; |Title = "ggg"
00407CA4 |. 68 007D4000 push 00407D00 ; |Text = "0000"
00407CA9 |. 6A 00 push 0 ; |hOwner = NULL
00407CAB |. E8 B8C8FFFF call <jmp.&user32.MessageBoxA> ; \MessageBoxA
00407CB0 |. EB 3D jmp short 00407CEF
00407CB2 |> 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL; Case 1 of switch 00407C91
00407CB4 |. 68 FC7C4000 push 00407CFC ; |Title = "ggg"
00407CB9 |. 68 087D4000 push 00407D08 ; |Text = "8899"
00407CBE |. 6A 00 push 0 ; |hOwner = NULL
00407CC0 |. E8 A3C8FFFF call <jmp.&user32.MessageBoxA> ; \MessageBoxA
00407CC5 |. EB 28 jmp short 00407CEF
00407CC7 |> 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL; Case 2 of switch 00407C91
00407CC9 |. 68 FC7C4000 push 00407CFC ; |Title = "ggg"
00407CCE |. 68 107D4000 push 00407D10 ; |Text = "2222"
00407CD3 |. 6A 00 push 0 ; |hOwner = NULL
00407CD5 |. E8 8EC8FFFF call <jmp.&user32.MessageBoxA> ; \MessageBoxA
00407CDA |. EB 13 jmp short 00407CEF
00407CDC |> 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL; Default case of switch 00407C91
00407CDE |. 68 FC7C4000 push 00407CFC ; |Title = "ggg"
00407CE3 |. 68 187D4000 push 00407D18 ; |Text = "78No"
00407CE8 |. 6A 00 push 0 ; |hOwner = NULL
00407CEA |. E8 79C8FFFF call <jmp.&user32.MessageBoxA> ; \MessageBoxA
//函数参数传递字符串问题, 这种形态对我来说, 逆向很是恼火。
直接填充函数参数一个串则为这种情形
00407C9C /$ B8 AC7C4000 mov eax, 00407CAC ;只通过一个eax, 得到一个临时变量区的地址来传递
00407CA1 |. E8 F2FFFFFF call 00407C98
[源]
test('6');
//而利用全局变量(存储器)进行中转的则为这种形态
00407C94 |. A1 A0824000 mov eax, dword ptr [4082A0]
00407C99 |. E8 EAFFFFFF call 00407C88
[源]
Init_funcStr(b);
//其中函数Init_funcStr和test的参数都是一个PChar类型, 并且没有加var, 因为加了var表示是一个引用,在内部就可以修改外部了。
//当反汇编看到
00407C9C /$ B8 AC7C4000 mov eax, 00407CAC ;只通过一个eax, 得到一个临时变量区的地址来传递
00407CA1 |. E8 F2FFFFFF call 00407C98
这种情形时就一定要想到 字符串一定是直接在实参部分写的, 而不是通过全局变量, 或局变量中转的。
//在局部变量(存储器)进行中转为
00407C90 |. B8 A87C4000 mov eax, 00407CA8 ; ASCII "0 :"
00407C95 |. E8 EAFFFFFF call 00407C84
[源]
szaBuf := '0 :';
Init_funcStr(szaBuf);
问题出现了, 利用局部变量和直接在函数实参数写为什么一样呢? 因为 都是利用堆栈临时填充的,也就是把串是存放在栈内。
00407C90 |. B8 A87C4000 mov eax, 00407CA8 ; ASCII "0 :"
00407C95 |. E8 EAFFFFFF call 00407C84
//看, 在同一个函数内, 直接在实参写串, 和利用临时变量转产生的是一样的。而
00407C9C /$ B8 AC7C4000 mov eax, 00407CAC ;只通过一个eax, 得到一个临时变量区的地址来传递
00407CA1 |. E8 F2FFFFFF call 00407C98 //这个之所以和上面的不一样是因为在不同的程序,不同的函数名编译的结果。
但是这里我们只关注 mov eax, <xxxxxx> 右操作数的形态, 不是存储器操作数就好, 要一个立即数的地址。
现在才刚刚开始, 更多逆向还在后面。
三、 高级情形, RTTI, 其他情形。
行1985: #########################################
上面大部分就是我反的并记录的笔记。
可是后来当试到PChar时, 发现和
00407C9C /$ B8 AC7C4000 mov eax, 00407CAC ;
00407CA1 |. E8 F2FFFFFF call 00407C98
这两句很类似了, 只不过我反出来的形态是这样的。
00407C94 |. A1 A0824000 mov eax, dword ptr [4082A0]
00407C99 |. E8 EAFFFFFF call 00407C88
也就是eax, 这行的操作数不对, 用过汇编的知道,很明显 dword ptr [4082A0]是个存储器操作数。
也就是说这个操作数是个变量。 而我要反的是个立即数,根据一些反汇编的经验,可以推测
这个立即数就是个地址。
于是我就想不是PChar类型的吧, 得到
00407C94 |. A1 A0824000 mov eax, dword ptr [4082A0]
00407C99 |. E8 EAFFFFFF call 00407C88
我是类似这么写的
var szBuf : PChar = '0 :';
function NewTestFunc(a : PChar):Integer;
begin
result := 0;
end;
funciton WinMain();stdcall;
begin
NewTestFunc(szBuf);
result := 0;
end;
这句 NewTestFunc(szBuf); 反出来就是
00407C94 |. A1 A0824000 mov eax, dword ptr [4082A0]
00407C99 |. E8 EAFFFFFF call 00407C88 相似的。
于是我又换成string类型的, 但是反出来还是不对。
后来还是试PChar, 因为我感觉就是操作数问题, 就是可能要变化变化。
于是不知怎么的, 我把调用方式改变了一下。 从NewTestFunc(szBuf)
改为 NewTestFunc('0 ');, 于是形态就正确了。
于是才联想起来由于直接写的 变量要放在堆栈内,所以只需要个地址就可以了。
而我再单独申请个局部变量然后在赋值后, 和直接写实参也一样, 好就到这, 这么反出来
工作量大些毕竟没多少经验, 但是逆出来两句也很高兴。