x32dbg/x64dbg逆向之反向分析还原c语言代码21) 反向分析还原c语言函数代码1咱们接着看下一个哦记好每次新的知识x64中为啥取值变化了rbpE0 rbpE8 rbpF0怎么来的0xE8(开辟空间)-0x20(修正值)0x10(2个Push)0x08(返回地址)0xE0数组特性连续宽度一致这段汇编代码是标准的数组取值ss:[rbp4] 取出来用movsxd指令把这个32位的数字符号扩展拉伸成64位的rax00007FF6CC3A1830 | 48:6345 04 | movsxd rax,dword ptr ss:[rbp4] | FileName.cpp:37, rax:__enc$textbss$end5A这里不是很理解数组取值00007FF6CC3A1834 | 48:8B8D 00010000 | mov rcx,qword ptr ss:[rbp100] | 第二和参数确认了这个就是第一个参数了获取数组的首地址最终内存地址 数组首地址(rcx) 下标(rax) × 每个元素的大小(4字节)00007FF6CC3A183B | 8B0C81 | mov ecx,dword ptr ds:[rcxrax*4] | 真正去数组里拿值00007FF6CC3A183E | E8 CAF9FFFF | call project1.7FF6CC3A120D | 调用咱们另一个自定义函数%操作两个新指令学习一下cdq记录正负 它主要负责的eax寄存器。如果eax里是正数它就把旁边的edx变成 0如果是负数它就把edx变成 -1。and eax, 1 只看最后一位如果是偶数下面两个操作因为奇数在and eax, 1之后如果是偶数eax0如果是奇数eax! 0。xor eax, edxsub eax, edxds:[even_count] 全局变量ss:[rsp 8] 局部变量咱们看下代码还原有哪些内容分析过程分析函数参数分析局部变量分析全局变量分析函数功能分析返回值最后还原c代码这一个星期课程咱们都是把汇编给反向还原到C语言哦坚持一下咱们从简单一点的代码然后再深一点一点还原咱们写的各种exe应用2汇编代码exe文件下载请从这里下载分别有DebugRelease两个版本。请自己反编译完成代码还原就好。https://download.csdn.net/download/Strategic__/93160031Debug版本 main如果找不到请参考逆向基础的第二课“x32dbg/x64dbg逆向之找main入口方式” 00007FF69FCF1A60 | 40:55 | push rbp | FileName.cpp:60 00007FF69FCF1A62 | 57 | push rdi | 00007FF69FCF1A63 | 48:81EC 08010000 | sub rsp,108 | 00007FF69FCF1A6A | 48:8D6C24 20 | lea rbp,qword ptr ss:[rsp20] | 00007FF69FCF1A6F | 48:8D0D 92050100 | lea rcx,qword ptr ds:[__14F49BB1_FileNamecpp] | FileName.cpp:15732480 00007FF69FCF1A76 | E8 31F9FFFF | call project1.7FF69FCF13AC | 00007FF69FCF1A7B | 90 | nop | 00007FF69FCF1A7C | C745 04 0C000000 | mov dword ptr ss:[rbp4],C | FileName.cpp:61, 0C:\f局部变量赋值c 12 第一个自定义函数开始 00007FF69FCF1A83 | 8B4D 04 | mov ecx,dword ptr ss:[rbp4] | FileName.cpp:62 00007FF69FCF1A86 | E8 84F5FFFF | call project1.7FF69FCF100F | 00007FF69FCF1A8B | 44:8BC0 | mov r8d,eax | 00007FF69FCF1A8E | 8B55 04 | mov edx,dword ptr ss:[rbp4] | 00007FF69FCF1A91 | 48:8D0D 90910000 | lea rcx,qword ptr ds:[Loop Factorial(%d) %d\n...] | 00007FF69FCFAC28:Loop Factorial(%d) %d\n 00007FF69FCF1A98 | E8 C0F7FFFF | call project1.7FF69FCF125D | printf 00007FF69FCF1A9D | 90 | nop | 第二个自定义函数开始 00007FF69FCF1A9E | 8B4D 04 | mov ecx,dword ptr ss:[rbp4] | FileName.cpp:63 00007FF69FCF1AA1 | E8 80F7FFFF | call project1.7FF69FCF1226 | 00007FF69FCF1AA6 | 44:8BC0 | mov r8d,eax | 00007FF69FCF1AA9 | 8B55 04 | mov edx,dword ptr ss:[rbp4] | 00007FF69FCF1AAC | 48:8D0D 95910000 | lea rcx,qword ptr ds:[Recursion Factorial(%d) %d\n...] | 00007FF69FCFAC48:Recursion Factorial(%d) %d\n 00007FF69FCF1AB3 | E8 A5F7FFFF | call project1.7FF69FCF125D | 00007FF69FCF1AB8 | 90 | nop | 第三个自定义函数开始 00007FF69FCF1AB9 | 8B4D 04 | mov ecx,dword ptr ss:[rbp4] | FileName.cpp:64 00007FF69FCF1ABC | E8 07F6FFFF | call project1.7FF69FCF10C8 | 00007FF69FCF1AC1 | 44:8BC0 | mov r8d,eax | 00007FF69FCF1AC4 | 8B55 04 | mov edx,dword ptr ss:[rbp4] | 00007FF69FCF1AC7 | 48:8D0D A2910000 | lea rcx,qword ptr ds:[Loop Fibonacci(%d) %d\n...] | 00007FF69FCFAC70:Loop Fibonacci(%d) %d\n 00007FF69FCF1ACE | E8 8AF7FFFF | call project1.7FF69FCF125D | 00007FF69FCF1AD3 | 90 | nop | 第四个自定义函数开始 00007FF69FCF1AD4 | 8B4D 04 | mov ecx,dword ptr ss:[rbp4] | FileName.cpp:65 00007FF69FCF1AD7 | E8 1EF6FFFF | call project1.7FF69FCF10FA | 00007FF69FCF1ADC | 44:8BC0 | mov r8d,eax | 00007FF69FCF1ADF | 8B55 04 | mov edx,dword ptr ss:[rbp4] | 00007FF69FCF1AE2 | 48:8D0D A7910000 | lea rcx,qword ptr ds:[Recursion Fibonacci(%d) %d\n...] | 00007FF69FCFAC90:Recursion Fibonacci(%d) %d\n 00007FF69FCF1AE9 | E8 6FF7FFFF | call project1.7FF69FCF125D | 00007FF69FCF1AEE | 90 | nop | 00007FF69FCF1AEF | 33C0 | xor eax,eax | FileName.cpp:66 00007FF69FCF1AF1 | 48:8DA5 E8000000 | lea rsp,qword ptr ss:[rbpE8] | FileName.cpp:67 00007FF69FCF1AF8 | 5F | pop rdi | 00007FF69FCF1AF9 | 5D | pop rbp | 00007FF69FCF1AFA | C3 | ret | 发现第一个自定义函数 参数0x128(开辟空间)-0x20(修正值)0x10(2个Push)0x08(返回地址)0x120 00007FF69FCF17F0 | 894C24 08 | mov dword ptr ss:[rsp8],ecx | FileName.cpp:11获取参数保存 00007FF69FCF17F4 | 55 | push rbp | 00007FF69FCF17F5 | 57 | push rdi | 00007FF69FCF17F6 | 48:81EC 28010000 | sub rsp,128 | 00007FF69FCF17FD | 48:8D6C24 20 | lea rbp,qword ptr ss:[rsp20] | 00007FF69FCF1802 | 48:8D0D FF070100 | lea rcx,qword ptr ds:[__14F49BB1_FileNamecpp] | FileName.cpp:15732480 00007FF69FCF1809 | E8 9EFBFFFF | call project1.7FF69FCF13AC | 00007FF69FCF180E | 90 | nop | 00007FF69FCF180F | C745 04 01000000 | mov dword ptr ss:[rbp4],1 | FileName.cpp:12两个局部变量赋值 00007FF69FCF1816 | C745 24 01000000 | mov dword ptr ss:[rbp24],1 | FileName.cpp:13但是第二个有点怪直接jmp循环 00007FF69FCF181D | EB 08 | jmp project1.7FF69FCF1827 | 00007FF69FCF181F | 8B45 24 | mov eax,dword ptr ss:[rbp24] | 00007FF69FCF1822 | FFC0 | inc eax | 00007FF69FCF1824 | 8945 24 | mov dword ptr ss:[rbp24],eax | 00007FF69FCF1827 | 8B85 20010000 | mov eax,dword ptr ss:[rbp120] | 开始和咱们参数比较 00007FF69FCF182D | 3945 24 | cmp dword ptr ss:[rbp24],eax | 开始和咱们参数比较 00007FF69FCF1830 | 7F 0C | jg project1.7FF69FCF183E | 如果大于跳出确定是循环了 00007FF69FCF1832 | 8B45 04 | mov eax,dword ptr ss:[rbp4] | FileName.cpp:14循环内部有个乘法操作 00007FF69FCF1835 | 0FAF45 24 | imul eax,dword ptr ss:[rbp24] | 00007FF69FCF1839 | 8945 04 | mov dword ptr ss:[rbp4],eax | 00007FF69FCF183C | EB E1 | jmp project1.7FF69FCF181F | 00007FF69FCF183E | 8B45 04 | mov eax,dword ptr ss:[rbp4] | FileName.cpp:15 00007FF69FCF1841 | 48:8DA5 08010000 | lea rsp,qword ptr ss:[rbp108] | FileName.cpp:16 00007FF69FCF1848 | 5F | pop rdi | 00007FF69FCF1849 | 5D | pop rbp | 00007FF69FCF184A | C3 | ret | 发现第二个自定义函数地址为7FF69FCF1226 参数0xE8(开辟空间)-0x20(修正值)0x10(2个Push)0x08(返回地址)0xE0 00007FF69FCF1780 | 894C24 08 | mov dword ptr ss:[rsp8],ecx | FileName.cpp:24获取参数保存 00007FF69FCF1784 | 55 | push rbp | 00007FF69FCF1785 | 57 | push rdi | 00007FF69FCF1786 | 48:81EC E8000000 | sub rsp,E8 | 00007FF69FCF178D | 48:8D6C24 20 | lea rbp,qword ptr ss:[rsp20] | [rsp20]:__scrt_release_startup_lockD 00007FF69FCF1792 | 48:8D0D 6F080100 | lea rcx,qword ptr ds:[__14F49BB1_FileNamecpp] | FileName.cpp:15732480 00007FF69FCF1799 | E8 0EFCFFFF | call project1.7FF69FCF13AC | 00007FF69FCF179E | 90 | nop | 00007FF69FCF179F | 83BD E0000000 01 | cmp dword ptr ss:[rbpE0],1 | FileName.cpp:25和咱们参数比较 00007FF69FCF17A6 | 7F 07 | jg project1.7FF69FCF17AF | 如果大于跳到7FF69FCF17AF 00007FF69FCF17A8 | B8 01000000 | mov eax,1 | FileName.cpp:26否则返回eax 1 是一个返回值 00007FF69FCF17AD | EB 1A | jmp project1.7FF69FCF17C9 | 00007FF69FCF17AF | 8B85 E0000000 | mov eax,dword ptr ss:[rbpE0] | FileName.cpp:27参数给eax 00007FF69FCF17B5 | FFC8 | dec eax | eax - 1 00007FF69FCF17B7 | 8BC8 | mov ecx,eax | 00007FF69FCF17B9 | E8 68FAFFFF | call project1.7FF69FCF1226 | 注意他自己调用自己了递归 00007FF69FCF17BE | 8B8D E0000000 | mov ecx,dword ptr ss:[rbpE0] | 每次自己调用自己完后 * 咱们参数 00007FF69FCF17C4 | 0FAFC8 | imul ecx,eax | 00007FF69FCF17C7 | 8BC1 | mov eax,ecx | 00007FF69FCF17C9 | 48:8DA5 C8000000 | lea rsp,qword ptr ss:[rbpC8] | FileName.cpp:28 00007FF69FCF17D0 | 5F | pop rdi | 00007FF69FCF17D1 | 5D | pop rbp | 00007FF69FCF17D2 | C3 | ret | 发现第三个自定义函数 参数0x168(开辟空间)-0x20(修正值)0x10(2个Push)0x08(返回地址)0x160 00007FF69FCF1870 | 894C24 08 | mov dword ptr ss:[rsp8],ecx | FileName.cpp:36一样操作哦 00007FF69FCF1874 | 55 | push rbp | 00007FF69FCF1875 | 57 | push rdi | 00007FF69FCF1876 | 48:81EC 68010000 | sub rsp,168 | 开辟空间记住上面公式哦 00007FF69FCF187D | 48:8D6C24 20 | lea rbp,qword ptr ss:[rsp20] | 00007FF69FCF1882 | 48:8D0D 7F070100 | lea rcx,qword ptr ds:[__14F49BB1_FileNamecpp] | FileName.cpp:15732480 00007FF69FCF1889 | E8 1EFBFFFF | call project1.7FF69FCF13AC | 00007FF69FCF188E | 90 | nop | 00007FF69FCF188F | C745 04 00000000 | mov dword ptr ss:[rbp4],0 | FileName.cpp:37咱们只传了一个参数但是通过计算不是 00007FF69FCF1896 | C745 24 01000000 | mov dword ptr ss:[rbp24],1 | 所以这个三个是函数内部的局部变量 00007FF69FCF189D | C745 64 02000000 | mov dword ptr ss:[rbp64],2 | FileName.cpp:38 00007FF69FCF18A4 | EB 08 | jmp project1.7FF69FCF18AE | 跟着jmp那有可能是循环那上面三个参数有一个是i变量 00007FF69FCF18A6 | 8B45 64 | mov eax,dword ptr ss:[rbp64] | 00007FF69FCF18A9 | FFC0 | inc eax | 00007FF69FCF18AB | 8945 64 | mov dword ptr ss:[rbp64],eax | 00007FF69FCF18AE | 8B85 60010000 | mov eax,dword ptr ss:[rbp160] | 开始比较了那就是循环了 00007FF69FCF18B4 | 3945 64 | cmp dword ptr ss:[rbp64],eax | 开始和函数中的局部变量比较 00007FF69FCF18B7 | 7F 1B | jg project1.7FF69FCF18D4 | 如果大于跳出循环 00007FF69FCF18B9 | 8B45 24 | mov eax,dword ptr ss:[rbp24] | FileName.cpp:40 00007FF69FCF18BC | 8B4D 04 | mov ecx,dword ptr ss:[rbp4] | 循环内两个变量相加 00007FF69FCF18BF | 03C8 | add ecx,eax | 00007FF69FCF18C1 | 8BC1 | mov eax,ecx | 00007FF69FCF18C3 | 8945 44 | mov dword ptr ss:[rbp44],eax | 把最终结果给某一个局部变量根据下面内容是返回使用的 00007FF69FCF18C6 | 8B45 24 | mov eax,dword ptr ss:[rbp24] | FileName.cpp:41 00007FF69FCF18C9 | 8945 04 | mov dword ptr ss:[rbp4],eax | 00007FF69FCF18CC | 8B45 44 | mov eax,dword ptr ss:[rbp44] | FileName.cpp:42 00007FF69FCF18CF | 8945 24 | mov dword ptr ss:[rbp24],eax | 00007FF69FCF18D2 | EB D2 | jmp project1.7FF69FCF18A6 | FileName.cpp:43 00007FF69FCF18D4 | 8B45 24 | mov eax,dword ptr ss:[rbp24] | FileName.cpp:44 00007FF69FCF18D7 | 48:8DA5 48010000 | lea rsp,qword ptr ss:[rbp148] | FileName.cpp:45 00007FF69FCF18DE | 5F | pop rdi | 00007FF69FCF18DF | 5D | pop rbp | 00007FF69FCF18E0 | C3 | ret | 发现第四个自定义函数的地址 参数0xF8(开辟空间)-0x20(修正值)0x10(2个Push)0x08(返回地址)0xF0 00007FF69FCF1900 | 894C24 08 | mov dword ptr ss:[rsp8],ecx | FileName.cpp:53 00007FF69FCF1904 | 55 | push rbp | 00007FF69FCF1905 | 57 | push rdi | 00007FF69FCF1906 | 48:81EC F8000000 | sub rsp,F8 | 00007FF69FCF190D | 48:8D6C24 20 | lea rbp,qword ptr ss:[rsp20] | [rsp20]:_initterm58 00007FF69FCF1912 | 48:8D0D EF060100 | lea rcx,qword ptr ds:[__14F49BB1_FileNamecpp] | FileName.cpp:15732480 00007FF69FCF1919 | E8 8EFAFFFF | call project1.7FF69FCF13AC | 00007FF69FCF191E | 90 | nop | 00007FF69FCF191F | 83BD F0000000 02 | cmp dword ptr ss:[rbpF0],2 | FileName.cpp:54和第一个函数类似就说了if 00007FF69FCF1926 | 7F 07 | jg project1.7FF69FCF192F | 00007FF69FCF1928 | B8 01000000 | mov eax,1 | FileName.cpp:55 00007FF69FCF192D | EB 2D | jmp project1.7FF69FCF195C | 00007FF69FCF192F | 8B85 F0000000 | mov eax,dword ptr ss:[rbpF0] | FileName.cpp:56else 获取参数 00007FF69FCF1935 | FFC8 | dec eax | 参数 - 1 00007FF69FCF1937 | 8BC8 | mov ecx,eax | 继续调用自身 00007FF69FCF1939 | E8 BCF7FFFF | call project1.7FF69FCF10FA | 00007FF69FCF193E | 8985 C0000000 | mov dword ptr ss:[rbpC0],eax | 获取结果 00007FF69FCF1944 | 8B8D F0000000 | mov ecx,dword ptr ss:[rbpF0] | 00007FF69FCF194A | 83E9 02 | sub ecx,2 | 参数 - 2 00007FF69FCF194D | E8 A8F7FFFF | call project1.7FF69FCF10FA | 继续调用自身两此调用自身 00007FF69FCF1952 | 8B8D C0000000 | mov ecx,dword ptr ss:[rbpC0] | 00007FF69FCF1958 | 03C8 | add ecx,eax | 最后俩次调用相加返回结果 00007FF69FCF195A | 8BC1 | mov eax,ecx | 00007FF69FCF195C | 48:8DA5 D8000000 | lea rsp,qword ptr ss:[rbpD8] | FileName.cpp:57 00007FF69FCF1963 | 5F | pop rdi | 00007FF69FCF1964 | 5D | pop rbp | 00007FF69FCF1965 | C3 | ret | Release版本 release虽然优化过它不像前几个了所以咱们需要认真的去分析一下。 release优化的目的可以说是不择手段让程序跑得更快。它会丢弃很多东西rbp栈帧把变量全部塞进寄存器甚至重写咱们的数学公式。这就是为什么咱们在下面这段汇编里 再也看不到任何 mov [rbpxx], eax这种规规矩矩的局部变量读写了全是在寄存器之间神仙打架。 虽然他是神仙咱们作为凡人也有找到一个关键点帮助咱们理解release程序。在Release里代码会变但硬编码的字符串内容绝对不会变。 函数头部保存rbpsub rsp, 20在栈上一次性开辟了32字节正式进入神仙打架了 00007FF600CC10E0 | 40:53 | push rbx | FileName.cpp:60 00007FF600CC10E2 | 48:83EC 20 | sub rsp,20 | 循环阶乘开始 00007FF600CC10E6 | BB 01000000 | mov ebx,1 | FileName.cpp:62 ebx 1 00007FF600CC10EB | 44:8BC3 | mov r8d,ebx | r8d 1 00007FF600CC10EE | 8BC3 | mov eax,ebx | eax 1 00007FF600CC10F0 | 44:0FAFC0 | imul r8d,eax | 1 * 1 00007FF600CC10F4 | FFC0 | inc eax | 1 2 00007FF600CC10F6 | 83F8 0C | cmp eax,C | 0C:\f比较 i 12 00007FF600CC10F9 | 7E F5 | jle project1.7FF600CC10F0 | 如果不继续循环这个操作那就是阶乘算法 1*1 2*2 3*3... 00007FF600CC10FB | BA 0C000000 | mov edx,C | 0C:\f 00007FF600CC1100 | 48:8D0D F9100000 | lea rcx,qword ptr ds:[Loop Factorial(%d) %d\n...] | 00007FF600CC2200:Loop Factorial(%d) %d\n 00007FF600CC1107 | E8 04FFFFFF | call project1.printf | 递归计算阶乘这个有点复杂别急带着各位看一下 神奇计算公式咱们可以把rax看成未知数x。所以 x 2x 3x。 带入实际数字39,916,800 * 3 119,750,400 shl 左移2位变成 4倍 最终结果是479001600 00007FF600CC110C | B9 0B000000 | mov ecx,B | FileName.cpp:63, 0B:\vecx 11 00007FF600CC1111 | E8 5AFFFFFF | call project1.int __cdecl fact_rec(int) | 直接调用fact_rec去算11的阶乘注意rax返回值39,916,800 00007FF600CC1116 | BA 0C000000 | mov edx,C | 0C:\fedx 12 00007FF600CC111B | 48:8D0D FE100000 | lea rcx,qword ptr ds:[Recursion Factorial(%d) %d\n...] | 00007FF600CC2220:Recursion Factorial(%d) %d\n 00007FF600CC1122 | 44:8D0440 | lea r8d,qword ptr ds:[raxrax*2] | 这里有个神奇地方 r8d rax 2 * rax 00007FF600CC1126 | 41:C1E0 02 | shl r8d,2 | 左移2位等于乘以 4。3 * 4 12这就拼出了乘以12 00007FF600CC112A | E8 E1FEFFFF | call project1.printf | 循环计算斐波那契 有个规定掌握就行了 初始化 rbx1r8d0 第 1 圈 edx10 eax101r8d1rbx1 第 2 圈 edx9 eax112r8d1rbx2 第 3 圈 edx8 eax213r8d2rbx3 第 4 圈 edx7 eax325r8d3rbx5 第 5 圈 edx6 eax538r8d5rbx8 第 6 圈 edx5 eax8513r8d8rbx13 第 7 圈 edx4 eax13821r8d13rbx21 第 8 圈 edx3 eax211334r8d21rbx34 第 9 圈 edx2 eax342155r8d34rbx55 第 10 圈 edx1 eax553489r8d55rbx89 第 11 圈 edx0最后一圈 eax8955144r8d89rbx144 00007FF600CC112F | 45:33C0 | xor r8d,r8d | FileName.cpp:64r8d 0 00007FF600CC1132 | BA 0B000000 | mov edx,B | FileName.cpp:62, 0B:\v11 00007FF600CC1137 | 66:0F1F8400 00000000 | nop word ptr ds:[raxrax],ax | 00007FF600CC1140 | 42:8D0403 | lea eax,qword ptr ds:[rbxr8] | FileName.cpp:64 ebx 1 0 00007FF600CC1144 | 44:8D03 | lea r8d,qword ptr ds:[rbx] | 1 00007FF600CC1147 | 8BD8 | mov ebx,eax | 1 00007FF600CC1149 | 83EA 01 | sub edx,1 | 11 - 1 00007FF600CC114C | 75 F2 | jne project1.7FF600CC1140 | 00007FF600CC114E | 44:8BC0 | mov r8d,eax | 00007FF600CC1151 | 48:8D0D E8100000 | lea rcx,qword ptr ds:[Loop Fibonacci(%d) %d\n...] | 00007FF600CC2240:Loop Fibonacci(%d) %d\n 00007FF600CC1158 | BA 0C000000 | mov edx,C | 0C:\f 00007FF600CC115D | E8 AEFEFFFF | call project1.printf | 递归计算斐波那契 这个比上一个简单 00007FF600CC1162 | B9 0A000000 | mov ecx,A | FileName.cpp:65, 0A:\necx 10 00007FF600CC1167 | E8 34FFFFFF | call project1.int __cdecl fib_rec(int) | 第一次调用递归函数去算第 10 项 00007FF600CC116C | B9 0B000000 | mov ecx,B | 0B:\v ecx 11 00007FF600CC1171 | 44:8BC0 | mov r8d,eax | 把刚刚算好的10 给r8d 00007FF600CC1174 | E8 27FFFFFF | call project1.int __cdecl fib_rec(int) | 第二次调用递归函数 00007FF600CC1179 | 44:03C0 | add r8d,eax | 把第二次和第一次结果相加 00007FF600CC117C | 48:8D0D DD100000 | lea rcx,qword ptr ds:[Recursion Fibonacci(%d) %d\n...] | 00007FF600CC2260:Recursion Fibonacci(%d) %d\n 00007FF600CC1183 | BA 0C000000 | mov edx,C | 0C:\f 00007FF600CC1188 | E8 83FEFFFF | call project1.printf | 函数尾部神仙们清理战场回家咯 00007FF600CC118D | 33C0 | xor eax,eax | FileName.cpp:66 00007FF600CC118F | 48:83C4 20 | add rsp,20 | FileName.cpp:67 00007FF600CC1193 | 5B | pop rbx | 00007FF600CC1194 | C3 | ret |3还原的C语言代码咱们会带着各位简单过一遍哦关键部分会标注好剩下部分请自己逆向分析并还原成C语言考虑到一些初学者还是不很理解下面是部分伪代码和说明实际代码不写哦Release版本优化很多地方如果Release不好理解可以参考Debug版本的汇编进行代码还原操作。有个全局变量MAX_NUM 100000;通过上面的汇编分析咱们可以知道这几个点有四个函数int test(一个参数){有个循环操作循环内部有乘法操作}int test1(一个参数){有个递归操作一个参数 * test1一个参数 - 1}int test2(一个参数){有个条件操作不成立返回 1}int test3(一个参数){有个递归两次调用自身操作test3(一个参数 - 1) test1(一个参数 - 2);}main(){都是打印操作}https://download.csdn.net/download/Strategic__/93160029反向分析C语言代码可以在这里自行下载哦前提你自己实现过一遍了大部分都是过去帮国外客户授课指导教学时候给的内容如果接触过国外计算机相关的内容应该知道CSAssignmentCITS2002-SIFSCOMP 3350-Computer Organization and Assembly Language等等。正向咱们写的够多了吧这1年各种汇编c/c那如果反正来呢把某个语言下写的功能用其他语言来实现很多人叫代码还原代码互换咱们用自己的话来理解一下代码还原是从汇编反向推导出程序原本的c/c逻辑想要完整还原一模一样的源码其实很难实现特别release大量优化的时候但咱们做逆向重点不是拿源码而是吃透整套软件实现流程就行。原因很简单咱们只要吃透了软件整体逻辑和各个功能的底层原理咱们完全能用任意编程语言重新实现相同功能就算只用汇编也能单独复刻程序里某一个模块。咱们日常开发无非就是CRUD各种业务各种功能各种算法各种数据结构各种网络通信各种第三方库调用WinAPI调用各种加密各种模块各种新的开发框架各种套路对吧https://download.csdn.net/download/Strategic__/93160029
阅读完成 · 觉得有帮助?