呕心沥血两小时 终于弄的差不多了
好累啊 眼都花了。。。最近我连睡觉都拿汇编书当枕头 ,果然有点效果。
那个帖子太长了 我就自己发个小贴。
编译的EXE在 https://bbs.bccn.net/thread-375040-1-1.html 一楼。
完全以zklhp编译的EXE为目标,如果用其他的编译器,结果大概会有不同。
比如如果用VC,或者大概也许不会有and esp, 0FFFFFFF0h这个使esp后4位为0。
即使用同一个编译器 ,加上不同的编译参数,结果也可能不同。比如是否使用ebp指针。
复制一遍
程序代码:
#include <stdio.h> #include <string.h> int main(void) { char a[64] = {0}; strcpy(a, "我用这个数组放一个字符串"); printf("a是:%s\n", a); { //这是个大括号里面 char b[64] = {0}; strcpy(b, a); printf("b是:%s\n", b); } //理论上到这里b就释放了 char c[64] = "这里再有一个字符串应该是不增加堆栈大小才对"; printf("c是:%s\n", c); return 0; }
分析参数和局部变量这些问题,如果仅靠看源码或者凭已有知识进行的想象,还是很难了解透彻。
编译好EXE以后,进行反汇编,这个是最直接最快捷最有效的了。
下面就是我花了2个小时一条一条琢磨出来的。
这些指令 ,单单的任挑一条出来,都可以查百度查资料知道是什么意思,
困难的是几条指令合起来是什么意思。。。
都进行了分段和注释,明天再总结,今天头
程序代码:
.text:004013B7 ; Attributes: bp-based frame .text:004013B7 .text:004013B7 sub_4013B7 proc near ; CODE XREF: sub_401000+B4p .text:004013B7 .text:004013B7 var_DC = dword ptr -0DCh .text:004013B7 var_D8 = dword ptr -0D8h .text:004013B7 var_CC = byte ptr -0CCh .text:004013B7 var_8C = byte ptr -8Ch .text:004013B7 var_61 = byte ptr -61h .text:004013B7 var_4C = byte ptr -4Ch .text:004013B7 .text:004013B7 push ebp .text:004013B8 mov ebp, esp .text:004013BA push edi .text:004013BB push esi .text:004013BC push ebx .text:004013BD and esp, 0FFFFFFF0h ;调整堆栈指针使之按16字节对齐 .text:004013C0 sub esp, 0D0h ;开辟堆栈空间,大小为D0 .text:004013C6 call sub_4019B4 .text:004013CB lea ebx, [esp+0DCh+var_4C] .text:004013D2 mov al, 0 ;填充内容为0 .text:004013D4 mov edx, 40h ;数量40h .text:004013D9 mov edi, ebx .text:004013DB mov ecx, edx .text:004013DD rep stosb ;从地址[esp+0DCh+var_4C]开始初始化40h个字节内容为0。 .text:004013DF lea eax, [esp+0DCh+var_4C] .text:004013E6 mov edx, eax .text:004013E8 mov ebx, offset aTSO ; "我用这个数组放一个字符串" .text:004013ED mov eax, 19h ;19h个字节的数据 .text:004013F2 mov edi, edx .text:004013F4 mov esi, ebx .text:004013F6 mov ecx, eax .text:004013F8 rep movsb ; ;将19h个字节的字符串数据传送到堆栈地址[esp+0DCh+var_4C]为开始地址。 .text:004013FA lea eax, [esp+0DCh+var_4C] .text:00401401 mov [esp+0DCh+var_D8], eax ;传参数二 .text:00401405 mov [esp+0DCh+var_DC], offset aAGS ; "a是:%s\n";传参数一 .text:0040140C call sub_40138C ;调用printf函数 .text:00401411 lea ebx, [esp+0DCh+var_CC] .text:00401415 mov al, 0 .text:00401417 mov edx, 40h .text:0040141C mov edi, ebx .text:0040141E mov ecx, edx .text:00401420 rep stosb ;用0初始化堆栈地址[esp+0DCh+var_CC]开始的40h个字节的空间。 .text:00401422 lea eax, [esp+0DCh+var_4C] .text:00401429 mov [esp+0DCh+var_D8], eax ;把刚才传送到堆栈内的字符串数据地址作为strcpy的第2参数 .text:0040142D lea eax, [esp+0DCh+var_CC] ;将刚初始化的40h个字节的堆栈空间首地址作为strcpy的第1参数传递 .text:00401431 mov [esp+0DCh+var_DC], eax .text:00401434 call strcpy ; .text:00401439 lea eax, [esp+0DCh+var_CC] .text:0040143D mov [esp+0DCh+var_D8], eax ;传二参 .text:00401441 mov [esp+0DCh+var_DC], offset aBGS ; "b是:%s\n" ;传一参 .text:00401448 call sub_40138C ;调用printf函数 .text:0040144D lea edx, [esp+0DCh+var_8C] .text:00401451 mov ebx, offset aTQOJB ; "这里再有一个字符串应该是不增加堆栈大小?... .text:00401456 mov eax, 2Bh ;需传送的字节数为2bh .text:0040145B mov edi, edx ;目的 .text:0040145D mov esi, ebx ;源 .text:0040145F mov ecx, eax ;计数2bh .text:00401461 rep movsb ;把字符串传送至堆栈[esp+0DCh+var_8C]开始的2bh个字节中。 .text:00401463 lea ebx, [esp+0DCh+var_61] .text:00401467 mov al, 0 .text:00401469 mov edx, 15h .text:0040146E mov edi, ebx .text:00401470 mov ecx, edx .text:00401472 rep stosb ;用0初始化堆栈地址[esp+0DCh+var_61]开始的15h个字节 .text:00401474 lea eax, [esp+0DCh+var_8C] .text:00401478 mov [esp+0DCh+var_D8], eax ;传二参 .text:0040147C mov [esp+0DCh+var_DC], offset aCGS ; "c是:%s\n" ;传一参 .text:00401483 call sub_40138C ;调用printf函数 .text:00401488 mov eax, 0 ;return 0 .text:0040148D lea esp, [ebp-0Ch] ;平衡堆栈 .text:00401490 pop ebx .text:00401491 pop esi .text:00401492 pop edi .text:00401493 pop ebp ;平衡堆栈 对应开头的4个PUSH .text:00401494 retn .text:00401494 sub_4013B7 endp .text:00401494晕