反汇编即把目标二进制机器码转为汇编代码的过程,该技术常用于软件破解、外挂技术、病毒分析、逆向工程、软件汉化等领域,学习和理解反汇编对软件调试、系统漏洞挖掘、内核原理及理解高级语言代码都有相当大的帮助,软件一切神秘的运行机制全在反汇编代码里面。

IF-单条件分支语句: 单分支结构配合and与or实现的验证.

  1. #include <stdio.h>
  2. int main(int argc, char* argv[])
  3. {
  4. int x = 10, y = 20, z = 30;
  5. if (x >= y)
  6. {
  7. printf("x >=y");
  8. }
  9. else if (z >= x && z >= y)
  10. {
  11. printf("z>=x and z>=y");
  12. }
  13. return 0;
  14. }
  1. 004113DE | C745 F8 0A000000 | mov dword ptr ss:[ebp-0x8],0xA | x = 10
  2. 004113E5 | C745 EC 14000000 | mov dword ptr ss:[ebp-0x14],0x14 | y = 20
  3. 004113EC | C745 E0 1E000000 | mov dword ptr ss:[ebp-0x20],0x1E | z = 30
  4. 004113F3 | 8B45 F8 | mov eax,dword ptr ss:[ebp-0x8] | eax = 10
  5. 004113F6 | 3B45 EC | cmp eax,dword ptr ss:[ebp-0x14] | cmp 10,20 => 10-20
  6. 004113F9 | 7C 19 | jl 0x411414 | 上方表达式10小于20则跳 (第一个表达式)
  7. 004113FB | 8BF4 | mov esi,esp | main.c:8, esi:__enc$textbss$end+109
  8. 004113FD | 68 58584100 | push consoleapplication1.415858 | 415858:"x >=y"
  9. 00411402 | FF15 14914100 | call dword ptr ds:[<&printf>] |
  10. 00411408 | 83C4 04 | add esp,0x4 |
  11. 0041140B | 3BF4 | cmp esi,esp | esi:__enc$textbss$end+109
  12. 0041140D | E8 24FDFFFF | call 0x411136 |
  13. 00411412 | EB 27 | jmp 0x41143B |
  14. 00411414 | 8B45 E0 | mov eax,dword ptr ss:[ebp-0x20] | eax = 30
  15. 00411417 | 3B45 F8 | cmp eax,dword ptr ss:[ebp-0x8] | cmp 30,10 => 30-10
  16. 0041141A | 7C 1F | jl 0x41143B | 上方表达式 30>10 jl不跳 (第二个表达式)
  17. 0041141C | 8B45 E0 | mov eax,dword ptr ss:[ebp-0x20] | eax = 30
  18. 0041141F | 3B45 EC | cmp eax,dword ptr ss:[ebp-0x14] | cmp 30,20 => 30>20
  19. 00411422 | 7C 17 | jl 0x41143B | 上方表达式 30>20 jl不跳 (第二个表达式)
  20. 00411424 | 8BF4 | mov esi,esp | main.c:12, esi:__enc$textbss$end+109
  21. 00411426 | 68 60584100 | push consoleapplication1.415860 | 415860:"z>=x and z>=y"
  22. 0041142B | FF15 14914100 | call dword ptr ds:[<&printf>] | 最后打印输出字符串
  23. 00411431 | 83C4 04 | add esp,0x4 |

if (z >= x && z >= y) 语句的表现形式

if (z >= x || z >= y) 稍微改变成或者,再来观察程序流程,两个结构对比,然后总结经验,或者与并且两个语句在实现上的异同点。

如果将代码编译为 Release 版本,你会发现if语句被优化没了,只保留了一个打印结果,这个优化还是很牛b的,整个结构都被重定义了。编译器认为你的判断没有任何意义,所以直接就给你干掉了,只保留了一个输出结果,这个输出结果是一定会被执行的,是一个定死的。

IF-嵌套条件分支:

  1. #include <stdio.h>
  2. int main(int argc, char* argv[])
  3. {
  4. int x = 10, y = 20, z = 30;
  5. if (x >= y || z >= x)
  6. {
  7. if (x <= z)
  8. {
  9. printf("x >=y or z>=x and x<=z");
  10. }
  11. else
  12. {
  13. printf("x >=y or z>=x and x>=z");
  14. }
  15. }
  16. return 0;
  17. }
  1. 004113DE | C745 F8 0A000000 | mov dword ptr ss:[ebp-0x8],0xA | 0xA = 10
  2. 004113E5 | C745 EC 14000000 | mov dword ptr ss:[ebp-0x14],0x14 | 0x14 = 20
  3. 004113EC | C745 E0 1E000000 | mov dword ptr ss:[ebp-0x20],0x1E | 0x1E = 30
  4. 004113F3 | 8B45 F8 | mov eax,dword ptr ss:[ebp-0x8] | eax = 10
  5. 004113F6 | 3B45 EC | cmp eax,dword ptr ss:[ebp-0x14] | cmp eax,20 => 10-20
  6. 004113F9 | 7D 08 | jge 0x411403 | 比较不成立,则不跳
  7. 004113FB | 8B45 E0 | mov eax,dword ptr ss:[ebp-0x20] | eax = 30
  8. 004113FE | 3B45 F8 | cmp eax,dword ptr ss:[ebp-0x8] | cpm eax,10 => 30-10
  9. 00411401 | 7C 38 | jl 0x41143B | 比较不成立,则不跳
  10. 00411403 | 8B45 F8 | mov eax,dword ptr ss:[ebp-0x8] | eax = 10
  11. 00411406 | 3B45 E0 | cmp eax,dword ptr ss:[ebp-0x20] | cpm eax,30 => 10-30
  12. 00411409 | 7F 19 | jg 0x411424 | 10不大于30则不跳
  13. 0041140B | 8BF4 | mov esi,esp | main.c:10
  14. 0041140D | 68 58584100 | push consoleapplication1.415858 | 415858:"x >=y or z>=x and x<=z"
  15. 00411412 | FF15 14914100 | call dword ptr ds:[<&printf>] | 打印出结果
  16. 00411418 | 83C4 04 | add esp,0x4 |

WHILE-循环: x++ 是jge来操控,++x是jg

  1. #include <stdio.h>
  2. int main(int argc, char* argv[])
  3. {
  4. int x = 0;
  5. while (x <= 10)
  6. {
  7. printf("打印: %d\n", x);
  8. x++;
  9. }
  10. return 0;
  11. }
  1. 004113DE | C745 F8 00000000 | mov dword ptr ss:[ebp-0x8],0x0 | 0
  2. 004113E5 | 837D F8 0A | cmp dword ptr ss:[ebp-0x8],0xA | cmp 0,10 =>
  3. 004113E9 | 7F 26 | jg 0x411411 | 0不大于10,则不跳
  4. 004113EB | 8BF4 | mov esi,esp | main.c:8
  5. 004113ED | 8B45 F8 | mov eax,dword ptr ss:[ebp-0x8] | eax = 0
  6. 004113F0 | 50 | push eax |
  7. 004113F1 | 68 58584100 | push consoleapplication1.415858 | 415858:"打印: %d\n"
  8. 004113F6 | FF15 14914100 | call dword ptr ds:[<&printf>] | 每次循环打印
  9. 004113FC | 83C4 08 | add esp,0x8 |
  10. 004113FF | 3BF4 | cmp esi,esp |
  11. 00411401 | E8 30FDFFFF | call 0x411136 | 微软堆栈检测器
  12. 00411406 | 8B45 F8 | mov eax,dword ptr ss:[ebp-0x8] | 取出eax里面的值
  13. 00411409 | 83C0 01 | add eax,0x1 | 每次递增1
  14. 0041140C | 8945 F8 | mov dword ptr ss:[ebp-0x8],eax |
  15. 0041140F | EB D4 | jmp 0x4113E5 | main.c:10
  16. 00411411 | 33C0 | xor eax,eax | main.c:11

在此基础上稍微增加难度,在while循环内部判断x是否能被2整除.

  1. #include <stdio.h>
  2. int main(int argc, char* argv[])
  3. {
  4. int x = 0;
  5. while (x <= 10)
  6. {
  7. printf("这是第: %d 次循环 \n", x+1);
  8. if (x % 2 == 0)
  9. printf("--> %d 次循环符合条件\n", x+1);
  10. x++;
  11. }
  12. return 0;
  13. }
  1. 004113DE | C745 F8 00000000 | mov dword ptr ss:[ebp-0x8],0x0 | 0
  2. 004113E5 | 837D F8 0A | cmp dword ptr ss:[ebp-0x8],0xA | cmp 0,0xA => 循环10
  3. 004113E9 | 7F 5A | jg 0x411445 | 0大于10则跳到结束
  4. 004113EB | 8B45 F8 | mov eax,dword ptr ss:[ebp-0x8] | 取出循环计数
  5. 004113EE | 83C0 01 | add eax,0x1 | 在此基础上+1
  6. 004113F1 | 8BF4 | mov esi,esp |
  7. 004113F3 | 50 | push eax | 压入堆栈
  8. 004113F4 | 68 58584100 | push consoleapplication1.415858 | 415858:"这是第: %d 次循环 \n"
  9. 004113F9 | FF15 14914100 | call dword ptr ds:[<&printf>] | 输出结果
  10. 004113FF | 83C4 08 | add esp,0x8 | 堆栈恢复
  11. 00411402 | 3BF4 | cmp esi,esp |
  12. 00411404 | E8 2DFDFFFF | call 0x411136 |
  13. 00411409 | 8B45 F8 | mov eax,dword ptr ss:[ebp-0x8] | main.c:9
  14. 0041140C | 25 01000080 | and eax,0x80000001 | 取出循环计数,并验证是否%2=0
  15. 00411411 | 79 05 | jns 0x411418 |
  16. 00411413 | 48 | dec eax |
  17. 00411414 | 83C8 FE | or eax,0xFFFFFFFE |
  18. 00411417 | 40 | inc eax |
  19. 00411418 | 85C0 | test eax,eax | 比较eax是否为0
  20. 0041141A | 75 1E | jne 0x41143A |
  21. 0041141C | 8B45 F8 | mov eax,dword ptr ss:[ebp-0x8] | main.c:10
  22. 0041141F | 83C0 01 | add eax,0x1 |
  23. 00411422 | 8BF4 | mov esi,esp |
  24. 00411424 | 50 | push eax |
  25. 00411425 | 68 70584100 | push consoleapplication1.415870 | 415870:"--> %d 次循环符合条件\n"
  26. 0041142A | FF15 14914100 | call dword ptr ds:[<&printf>] |
  27. 00411430 | 83C4 08 | add esp,0x8 |
  28. 00411433 | 3BF4 | cmp esi,esp |
  29. 00411435 | E8 FCFCFFFF | call 0x411136 |
  30. 0041143A | 8B45 F8 | mov eax,dword ptr ss:[ebp-0x8] | main.c:11
  31. 0041143D | 83C0 01 | add eax,0x1 |
  32. 00411440 | 8945 F8 | mov dword ptr ss:[ebp-0x8],eax |
  33. 00411443 | EB A0 | jmp 0x4113E5 | main.c:12
  34. 00411445 | 33C0 | xor eax,eax | main.c:13

继续修改源代码,增加双层循环,实现嵌套wihle循环.

  1. #include <stdio.h>
  2. int main(int argc, char* argv[])
  3. {
  4. int x = 0, y = 0, z =0 ;
  5. while (x <= 10)
  6. {
  7. while (y <= 5)
  8. {
  9. z = x + y;
  10. if (z %2==0)
  11. printf("外层循环: %d 内层循环: %d \n", x, y);
  12. y = y + 1;
  13. }
  14. x = x + 1;
  15. }
  16. return 0;
  17. }
  1. 004113DE | C745 F8 00000000 | mov dword ptr ss:[ebp-0x8],0x0 | x
  2. 004113E5 | C745 EC 00000000 | mov dword ptr ss:[ebp-0x14],0x0 | y
  3. 004113EC | C745 E0 00000000 | mov dword ptr ss:[ebp-0x20],0x0 | z
  4. 004113F3 | 837D F8 0A | cmp dword ptr ss:[ebp-0x8],0xA | 定义外层循环,总共循环10
  5. 004113F7 | 7F 57 | jg 0x411450 |
  6. 004113F9 | 837D EC 05 | cmp dword ptr ss:[ebp-0x14],0x5 | 定义内存循环,总共循环5
  7. 004113FD | 7F 46 | jg 0x411445 |
  8. 004113FF | 8B45 F8 | mov eax,dword ptr ss:[ebp-0x8] | eax = x
  9. 00411402 | 0345 EC | add eax,dword ptr ss:[ebp-0x14] | add x,y
  10. 00411405 | 8945 E0 | mov dword ptr ss:[ebp-0x20],eax | mov z = x+y
  11. 00411408 | 8B45 E0 | mov eax,dword ptr ss:[ebp-0x20] | main.c:11
  12. 0041140B | 25 01000080 | and eax,0x80000001 | 取出z的值
  13. 00411410 | 79 05 | jns 0x411417 |
  14. 00411412 | 48 | dec eax |
  15. 00411413 | 83C8 FE | or eax,0xFFFFFFFE |
  16. 00411416 | 40 | inc eax |
  17. 00411417 | 85C0 | test eax,eax | 取出z的值,判断是否%2==0
  18. 00411419 | 75 1F | jne 0x41143A |
  19. 0041141B | 8BF4 | mov esi,esp | main.c:12
  20. 0041141D | 8B45 EC | mov eax,dword ptr ss:[ebp-0x14] |
  21. 00411420 | 50 | push eax |
  22. 00411421 | 8B4D F8 | mov ecx,dword ptr ss:[ebp-0x8] |
  23. 00411424 | 51 | push ecx |
  24. 00411425 | 68 58584100 | push consoleapplication1.415858 | 415858:"外层循环: %d 内层循环: %d \n"
  25. 0041142A | FF15 14914100 | call dword ptr ds:[<&printf>] |
  26. 00411430 | 83C4 0C | add esp,0xC |
  27. 00411433 | 3BF4 | cmp esi,esp |
  28. 00411435 | E8 FCFCFFFF | call 0x411136 |
  29. 0041143A | 8B45 EC | mov eax,dword ptr ss:[ebp-0x14] | main.c:13
  30. 0041143D | 83C0 01 | add eax,0x1 |
  31. 00411440 | 8945 EC | mov dword ptr ss:[ebp-0x14],eax |
  32. 00411443 | EB B4 | jmp 0x4113F9 | 无条件跳转到内层循环
  33. 00411445 | 8B45 F8 | mov eax,dword ptr ss:[ebp-0x8] | main.c:15
  34. 00411448 | 83C0 01 | add eax,0x1 |
  35. 0041144B | 8945 F8 | mov dword ptr ss:[ebp-0x8],eax |
  36. 0041144E | EB A3 | jmp 0x4113F3 | 无条件跳转到外层循环
  37. 00411450 | 33C0 | xor eax,eax | main.c:17

这里的打印参数,很有趣,取值并压入两个参数,然后调用的printf.

DO-WHILE条件循环: 与while循环不同,do会先执行循环然后判断,如下代码反编译观察.

  1. #include <stdio.h>
  2. int main(int argc, char* argv[])
  3. {
  4. int x = 0,y=0;
  5. do
  6. {
  7. printf("外层do-while 循环: %d\n", x);
  8. while (y <= 5)
  9. {
  10. printf("内层while 循环: %d\n", y);
  11. y = y + 1;
  12. }
  13. x = x + 1;
  14. } while (x <= 10);
  15. return 0;
  16. }

如下反汇编代码可以观察到代码结构,C语言在实现while语句与do-while语句的异同点,while语句是先判断然后才会进入循环体,而do-while则是先执行循环体内部的东西,最后补一刀来判断是否满足条件.

  1. 004113DE | C745 F8 00000000 | mov dword ptr ss:[ebp-0x8],0x0 | x
  2. 004113E5 | C745 EC 00000000 | mov dword ptr ss:[ebp-0x14],0x0 | y
  3. 004113EC | 8BF4 | mov esi,esp | main.c:8
  4. 004113EE | 8B45 F8 | mov eax,dword ptr ss:[ebp-0x8] | mov eax,0
  5. 004113F1 | 50 | push eax |
  6. 004113F2 | 68 58584100 | push consoleapplication1.415858 | 415858:"外层do-while 循环: %d\n"
  7. 004113F7 | FF15 14914100 | call dword ptr ds:[<&printf>] |
  8. 004113FD | 83C4 08 | add esp,0x8 |
  9. 00411400 | 3BF4 | cmp esi,esp |
  10. 00411402 | E8 2FFDFFFF | call 0x411136 |
  11. 00411407 | 837D EC 05 | cmp dword ptr ss:[ebp-0x14],0x5 | 进入内层循环
  12. 0041140B | 7F 26 | jg 0x411433 | 直到条件大于5则退出
  13. 0041140D | 8BF4 | mov esi,esp | main.c:11
  14. 0041140F | 8B45 EC | mov eax,dword ptr ss:[ebp-0x14] |
  15. 00411412 | 50 | push eax |
  16. 00411413 | 68 74584100 | push consoleapplication1.415874 | 415874:"内层while 循环: %d\n"
  17. 00411418 | FF15 14914100 | call dword ptr ds:[<&printf>] |
  18. 0041141E | 83C4 08 | add esp,0x8 |
  19. 00411421 | 3BF4 | cmp esi,esp |
  20. 00411423 | E8 0EFDFFFF | call 0x411136 |
  21. 00411428 | 8B45 EC | mov eax,dword ptr ss:[ebp-0x14] | main.c:12
  22. 0041142B | 83C0 01 | add eax,0x1 | 每次递增
  23. 0041142E | 8945 EC | mov dword ptr ss:[ebp-0x14],eax |
  24. 00411431 | EB D4 | jmp 0x411407 | main.c:13
  25. 00411433 | 8B45 F8 | mov eax,dword ptr ss:[ebp-0x8] | main.c:14
  26. 00411436 | 83C0 01 | add eax,0x1 |
  27. 00411439 | 8945 F8 | mov dword ptr ss:[ebp-0x8],eax |
  28. 0041143C | 837D F8 0A | cmp dword ptr ss:[ebp-0x8],0xA | 外层循环的比较
  29. 00411440 | 7E AA | jle 0x4113EC | 小于则跳转
  30. 00411442 | 33C0 | xor eax,eax | main.c:16

FOR-条件循环:

  1. #include <stdio.h>
  2. int main(int argc, char* argv[])
  3. {
  4. int x;
  5. for (x = 0; x <= 10; x++)
  6. {
  7. printf("循环计数: %d\n", x);
  8. }
  9. return 0;
  10. }
  1. 004113DE | C745 F8 00000000 | mov dword ptr ss:[ebp-0x8],0x0 | 初始化 x=0
  2. 004113E5 | EB 09 | jmp 0x4113F0 | 跳转到比较语句处
  3. 004113E7 | 8B45 F8 | mov eax,dword ptr ss:[ebp-0x8] |
  4. 004113EA | 83C0 01 | add eax,0x1 | 每次递增x++
  5. 004113ED | 8945 F8 | mov dword ptr ss:[ebp-0x8],eax |
  6. 004113F0 | 837D F8 0A | cmp dword ptr ss:[ebp-0x8],0xA | 判断x是否为10 x<=10
  7. 004113F4 | 7F 1D | jg 0x411413 | 大于则跳转到结束
  8. 004113F6 | 8BF4 | mov esi,esp | main.c:8, esi:__enc$textbss$end+109
  9. 004113F8 | 8B45 F8 | mov eax,dword ptr ss:[ebp-0x8] |
  10. 004113FB | 50 | push eax | 压入当前循环次数,并打印
  11. 004113FC | 68 58584100 | push consoleapplication1.415858 | 415858:"循环计数: %d\n"
  12. 00411401 | FF15 14914100 | call dword ptr ds:[<&printf>] |
  13. 00411407 | 83C4 08 | add esp,0x8 |
  14. 0041140A | 3BF4 | cmp esi,esp | esi:__enc$textbss$end+109
  15. 0041140C | E8 25FDFFFF | call 0x411136 |
  16. 00411411 | EB D4 | jmp 0x4113E7 | 跳转到递增语句处
  17. 00411413 | 33C0 | xor eax,eax | main.c:10

接着实现多分支for循环,也就是循环内部嵌套循环,接下来通过一个9x9口诀表分析,观察汇编代码变化.

  1. #include <stdio.h>
  2. int main(int argc, char* argv[])
  3. {
  4. int x,y;
  5. for (x = 1; x <= 9; x++)
  6. {
  7. for (y = 1; y <= x; y++)
  8. {
  9. printf("%d*%d=%d\t", y, x, x*y);
  10. }
  11. printf("\n");
  12. }
  13. system("pause");
  14. return 0;
  15. }
  1. 004113DE | C745 F8 01000000 | mov dword ptr ss:[ebp-0x8],0x1 | x = 1
  2. 004113E5 | EB 09 | jmp 0x4113F0 |
  3. 004113E7 | 8B45 F8 | mov eax,dword ptr ss:[ebp-0x8] |
  4. 004113EA | 83C0 01 | add eax,0x1 | 外层循环计数器
  5. 004113ED | 8945 F8 | mov dword ptr ss:[ebp-0x8],eax |
  6. 004113F0 | 837D F8 09 | cmp dword ptr ss:[ebp-0x8],0x9 | 比较外层循环x是否大于9
  7. 004113F4 | 7F 5C | jg 0x411452 |
  8. 004113F6 | C745 EC 01000000 | mov dword ptr ss:[ebp-0x14],0x1 | y = 1
  9. 004113FD | EB 09 | jmp 0x411408 |
  10. 004113FF | 8B45 EC | mov eax,dword ptr ss:[ebp-0x14] |
  11. 00411402 | 83C0 01 | add eax,0x1 | 内层循环计数器递增
  12. 00411405 | 8945 EC | mov dword ptr ss:[ebp-0x14],eax |
  13. 00411408 | 8B45 EC | mov eax,dword ptr ss:[ebp-0x14] | y
  14. 0041140B | 3B45 F8 | cmp eax,dword ptr ss:[ebp-0x8] | cmp y,x
  15. 0041140E | 7F 29 | jg 0x411439 | 大于则跳
  16. 00411410 | 8B45 F8 | mov eax,dword ptr ss:[ebp-0x8] | main.c:11
  17. 00411413 | 0FAF45 EC | imul eax,dword ptr ss:[ebp-0x14] |
  18. 00411417 | 8BF4 | mov esi,esp |
  19. 00411419 | 50 | push eax |
  20. 0041141A | 8B4D F8 | mov ecx,dword ptr ss:[ebp-0x8] |
  21. 0041141D | 51 | push ecx |
  22. 0041141E | 8B55 EC | mov edx,dword ptr ss:[ebp-0x14] |
  23. 00411421 | 52 | push edx |
  24. 00411422 | 68 58584100 | push consoleapplication1.415858 | 415858:"%d*%d=%d\t"
  25. 00411427 | FF15 18914100 | call dword ptr ds:[<&printf>] | 输出三个参数
  26. 0041142D | 83C4 10 | add esp,0x10 |
  27. 00411430 | 3BF4 | cmp esi,esp |
  28. 00411432 | E8 04FDFFFF | call 0x41113B |
  29. 00411437 | EB C6 | jmp 0x4113FF | main.c:12
  30. 00411439 | 8BF4 | mov esi,esp | main.c:13
  31. 0041143B | 68 64584100 | push consoleapplication1.415864 | 415864:L"\n"
  32. 00411440 | FF15 18914100 | call dword ptr ds:[<&printf>] | 外层循环增加换行
  33. 00411446 | 83C4 04 | add esp,0x4 |
  34. 00411449 | 3BF4 | cmp esi,esp |
  35. 0041144B | E8 EBFCFFFF | call 0x41113B |
  36. 00411450 | EB 95 | jmp 0x4113E7 | main.c:14
  37. 00411452 | 68 68584100 | push consoleapplication1.415868 | main.c:15, 415868:"pause"==L"慰獵e"
  38. 00411457 | E8 49FCFFFF | call 0x4110A5 |
  39. 0041145C | 83C4 04 | add esp,0x4 |

x64dbg 摘要

iDA 摘要

SWITCH-条件选择结构: 这个结构很有意思,还原它也不是太难,主要是该结构通过查表得到执行哪条语句,只要找到分支所对应的表格就能逆向出不同分支的作用.

  1. #include <stdio.h>
  2. int main(int argc, char* argv[])
  3. {
  4. int x;
  5. scanf("%d", &x);
  6. switch (x)
  7. {
  8. case 0:
  9. printf("case 0"); break;
  10. case 1:
  11. printf("case 1"); break;
  12. case 2:
  13. printf("case 2"); break;
  14. case 3:
  15. printf("case 3"); break;
  16. default:
  17. printf("none"); break;
  18. }
  19. return 0;
  20. }
  1. 004113F9 | 8B45 F8 | mov eax,dword ptr ss:[ebp-0x8] | main.c:7
  2. 004113FC | 8985 30FFFFFF | mov dword ptr ss:[ebp-0xD0],eax | 假设输入的是1
  3. 00411402 | 83BD 30FFFFFF 03 | cmp dword ptr ss:[ebp-0xD0],0x3 | cmp 1,3
  4. 00411409 | 77 71 | ja 0x41147C | 高于则跳,跳到default
  5. 0041140B | 8B8D 30FFFFFF | mov ecx,dword ptr ss:[ebp-0xD0] | ecx = 输入的分支数字,此处是1
  6. 00411411 | FF248D D4144100 | jmp dword ptr ds:[ecx*4+<>] | jmp 1*4 + 0x4114D4
  7. 00411418 | 8BF4 | mov esi,esp | main.c:10
  8. 0041141A | 68 5C584100 | push consoleapplication1.41585C | 41585C:"case 0"
  9. 0041141F | FF15 18914100 | call dword ptr ds:[<&printf>] |
  10. 00411425 | 83C4 04 | add esp,0x4 |
  11. 00411428 | 3BF4 | cmp esi,esp |
  12. 0041142A | E8 0CFDFFFF | call 0x41113B |
  13. 0041142F | EB 62 | jmp 0x411493 |
  14. 00411431 | 8BF4 | mov esi,esp | main.c:12
  15. 00411433 | 68 64584100 | push consoleapplication1.415864 | 415864:"case 1"
  16. 00411438 | FF15 18914100 | call dword ptr ds:[<&printf>] |
  17. 0041143E | 83C4 04 | add esp,0x4 |

代码中有三个主分支,一个默认分支,所以这里能看到每个分支所对应的物理地址。

x64dbg 会将其标注为红色。

ida 的分析则更加强大。

分析C++中异常处理

异常处理是任何一门编程语言都存在的一个特性,同样C++也规定了异常处理的写法,但由于C++标准中并没有明确定义异常处理的实现流程,因此导致不同编译器厂商在实现异常处理时各有不同,我们将以VS2013编译器所生成的异常处理代码进行深入分析,其他编译器自行研究吧.

下来手动注册一个异常处理函数

  1. #include <iostream>
  2. #include <Windows.h>
  3. using namespace std;
  4. LONG __stdcall MyException1(_EXCEPTION_POINTERS *Ecptpoints)
  5. {
  6. printf("发生异常,触发异常处理\n");
  7. return 0;
  8. }
  9. int main(int argc, char* argv[])
  10. {
  11. SetUnhandledExceptionFilter(MyException1); //设置异常的回调函数
  12. int *ptr = 0;
  13. *ptr = 1;
  14. system("pause");
  15. return 0;
  16. }
  1. #include <iostream>
  2. #include <Windows.h>
  3. using namespace std;
  4. int main(int argc, char* argv[])
  5. {
  6. try
  7. {
  8. throw -1; //抛出int类型异常
  9. }
  10. catch (int e)
  11. {
  12. printf("抛出了int类型异常. \n");
  13. }
  14. catch (float e)
  15. {
  16. printf("抛出了float类型异常. \n");
  17. }
  18. return 0;
  19. }
  1. 00415220 | 55 | push ebp | main.cpp:7
  2. 00415221 | 8BEC | mov ebp,esp |
  3. 00415223 | 6A FF | push 0xFFFFFFFF |
  4. 00415225 | 68 E0904100 | push <__ehhandler$_main> | 压入异常回调函数
  5. 0041522A | 64:A1 00000000 | mov eax,dword ptr fs:[0] |
  6. 00415230 | 50 | push eax |
  7. 00415231 | 64:8925 00000000 | mov dword ptr fs:[0],esp | 注册异常回调处理函数
  8. 00415238 | 51 | push ecx | ecx:"榈K"
  9. 00415239 | 81EC E4000000 | sub esp,0xE4 |
  10. 0041523F | 53 | push ebx |
  11. 00415240 | 56 | push esi | esi:"榈K"
  12. 00415241 | 57 | push edi | edi:"榈K"
  13. 00415242 | 8DBD 0CFFFFFF | lea edi,dword ptr ss:[ebp-0xF4] |
  14. 00415248 | B9 39000000 | mov ecx,0x39 | ecx:"榈K", 39:'9'
  15. 0041524D | B8 CCCCCCCC | mov eax,0xCCCCCCCC |
  16. 00415252 | F3:AB | rep stosd |
  17. 00415254 | 8965 F0 | mov dword ptr ss:[ebp-0x10],esp |
  18. 00415257 | C745 FC 00000000 | mov dword ptr ss:[ebp-0x4],0x0 | 设置异常编号
  19. 0041525E | C785 10FFFFFF FFFFFFFF | mov dword ptr ss:[ebp-0xF0],0xFFFFFFFF | main.cpp:10
  20. 00415268 | 68 60E94100 | push <consoleapplication2.__TI1H> | 压入异常结构
  21. 0041526D | 8D85 10FFFFFF | lea eax,dword ptr ss:[ebp-0xF0] | 获取异常分配函数地址
  22. 00415273 | 50 | push eax |
  23. 00415274 | E8 A3BFFFFF | call 0x41121C | 调用异常分配函数
  24. 00415279 | 8BF4 | mov esi,esp | main.cpp:14
  25. 0041527B | 68 6CCC4100 | push consoleapplication2.41CC6C | 41CC6C:"抛出了int类型异常. \n"
  26. 00415280 | FF15 80014200 | call dword ptr ds:[<&printf>] |
  27. 00415286 | 83C4 04 | add esp,0x4 |

C/C++ 反汇编:流程控制与循环结构的更多相关文章

  1. 053 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 15 流程控制知识总结

    053 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 15 流程控制知识总结 本文知识点: 流程控制知识总结 流程控制知识总结 选择结构语句 循环结构语句 ...

  2. 052 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 14 Eclipse下程序调试——debug2 多断点调试程序

    052 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 14 Eclipse下程序调试--debug2 多断点调试程序 本文知识点: Eclipse下程序调 ...

  3. 051 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 13 Eclipse下程序调试——debug入门1

    051 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 13 Eclipse下程序调试--debug入门1 本文知识点: 程序调试--debug入门1 程序 ...

  4. 050 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 12 continue语句

    050 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 12 continue语句 本文知识点:continue语句 continue语句 continue ...

  5. 049 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 11 break语句

    049 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 11 break语句 本文知识点:break语句 break语句 break语句前情回顾 1.swi ...

  6. 048 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 10 案例——阶乘的累加和

    048 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 10 案例--阶乘的累加和 本文知识点:通过案例练习嵌套循环应用 案例练习--阶乘的累加和 案例题目 ...

  7. 047 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 09 嵌套while循环应用

    047 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 09 嵌套while循环应用 本文知识点:嵌套while循环应用 什么是循环嵌套? 什么是循环嵌套? ...

  8. 046 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 08 for循环的注意事项

    046 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 08 for循环的注意事项 本文知识点:for循环的注意事项 for循环的注意事项 for循环有3个 ...

  9. 045 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 07 for循环应用及局部变量作用范围

    045 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 07 for循环应用及局部变量作用范围 本文知识点:for循环应用及局部变量作用范围 for循环 w ...

  10. 044 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 06 使用do-while循环实现猜字游戏

    044 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 06 使用do-while循环实现猜字游戏 本文知识点:do-while循环深入运用 案例练习 案例 ...

随机推荐

  1. 你不知道的vue3:使用runWithContext实现在非 setup 期间使用inject

    前言 日常开发时有些特殊的场景需要在非 setup 期间调用inject函数,比如app中使用provide注入的配置信息需要在发送http请求时带上传给后端.对此我们希望不在每个发起请求的地方去修改 ...

  2. Deltix Round, Summer 2021 Div1 + Div2 A~E

    比赛链接:Here 1556A. A Variety of Operations 注意到2, 3操作不改变总和,1操作使得总和加上了一个偶数,故直接判断总和是否为偶数即可.如果和为偶数,只要判断c和d ...

  3. POJ 1011 Sticks​ (DFS + 剪枝)

    题目地址:http://poj.org/problem?id=1011 题目大意 给出n个小木棒,组合成若干长度最短棍子 解题思路 首先将木棒从大到小排序 dfs(k, l), k是还剩多少木棒没用, ...

  4. 【每日一题】21.边的染色 (DFS连通图 + 思维)

    补题链接:Here 思维不够,看到这种陌生的题目无从下手. 这题应该做过一次的人会觉得它其实并不难. 主要思想:把边权->点权. 这样做的好处是,无论你怎么分配点权,在环内的异或值一定为 \(0 ...

  5. springboot+vue实现 下载服务端返回的文件功能

    开发中会遇到,通过浏览器下载服务器端返回的文件功能,本文使用springboot+vue实现该功能. 后端代码: 注:后端返回的文件名遇到中文就会乱码,一直也没得到很好的解决方案,最后就统一返回1.x ...

  6. 概率图模型 · 概率论基础 | 讲的非常好的 KL 散度博客

    知乎博客链接:https://zhuanlan.zhihu.com/p/425693597 感觉讲的非常好,谢谢善良的博主

  7. 搬运 |(有刀🔪慎入)kwdnx、谷雨、更漏与我

    本打算把文案投到官微,但官微说文案太长了,只能放删减版: 那就把文案放博客上吧 写于 癸卯年 戊午月 己亥日. 四年前的冬天我们初见,大家都是青涩的未成年人:在少年班团建的喧闹中,谷雨谈论高数竞赛,k ...

  8. nginx.conf 配置解析及常用配置

    本文为博主原创,未经允许不得转载: nginx.conf 配置文件配置解析 #定义 Nginx 运行的用户和用户组.默认nginx的安装用户为 nobody user www www: #启动进程,通 ...

  9. 安卓系统如何使用谷歌框架下的app?

    1.问题 安卓系统从理论上无法使用谷歌框架下的应用(比如像GMail,YouTube,Google play等等),会导致一些麻烦(闪退,卡在登陆界面等等) 注意:使用前提是会魔法,否则请绕道 2.解 ...

  10. 百度网盘(百度云)SVIP超级会员共享账号每日更新(2024.01.23)

    一.百度网盘SVIP超级会员共享账号 可能很多人不懂这个共享账号是什么意思,小编在这里给大家做一下解答. 我们多知道百度网盘很大的用处就是类似U盘,不同的人把文件上传到百度网盘,别人可以直接下载,避免 ...