c++反汇编逆向还原代码,数组元素的获取、初始化、循环的实现,shl指令、数组的初始化、元素的选取的汇编还原是本次笔记的重点
一、汇编
流程图片太大,所以分成两部分
本次用到的指令
mov :将源操作数复制到目的操作数
lea :与mov类似
mov a,b 表示将b赋值给a 若是 mov a,[b] 这是将b的地址赋值给a,相当于指针
jmp 跳转指令
cmp :比较
jg : jle 前面>后面
push:压栈
上面这些指令的详情解释可以看本笔记专栏的关于这些指令的介绍文章
点我跳转——c++反汇编逆向还原指令jge jg jle jl jne je
shl : 左移 比如shl eax,5 就是左移动两位 逆向还原时可以写成eax*2^5
二、代码还原
2.1认识数组初始化
可以看到,push了0x190 还有0 ,其实就是开辟了0x190字节大小的空间,把其中的元素赋值0
0是int类型的,因为int类型是4字节,所以用计算器计算0x190/4 再转换成10进制便是数组的大小
所以我们的ebp_arr大小是100,所以上面的数组初始化可以还原为
int ebp_arr[100]={0};
2.2认识数组元素选择
mov eax, [ebp+i]
lea ecx, [ebp+eax*4+arr]我们在前面可以看到汇编中的数组其实是
lea eax, [ebp+arr]
选择数组时,在这中间加了eax*4,变成了
lea ecx, [ebp+eax*4+arr]
int数组是4字节的,所以我们要在选择的索引上*4,eax便是索引
这里所以我们可以还原为
scanf("%d",&ebp_arr[ebp_i]);
从一可以知道shl 可以还原成eax=eax*2^2
mov eax, 4
shl eax, 2
mov ecx, [ebp+eax+arr] 等于mov ecx, [ebp+4*4+arr]
push ecx
push offset aD ; "%d\n"
call j__printf所以我们根据ecx, [ebp+4*4+arr]可以知道选中的索引4为
还原
printf("%d",ebp_arr[4]);
2.3汇编代码还原
原原本本按照汇编还原
#include<stdio.h>
int main(){
int ebp_n=0;
scanf("%d",&ebp_n);
int ebp_arr[100]={0};
int ebp_i=0;
for(;ebp_i<ebp_n;){
int eax=ebp_i;
scanf("%d",&ebp_arr[ebp_i]);
ebp_i+=1;
}
int ebp_sum=0;
int ebp_var_1C8=0;
for(;ebp_var_1C8<ebp_n;){
int eax=ebp_var_1C8;
int ecx=ebp_sum;
ecx=ecx+ebp_arr[ebp_var_1C8];
ebp_sum=ecx;
ebp_var_1C8+=1;
}
printf("%d\n",ebp_arr[4]);
printf("%d",ebp_sum);
return 0;
}
正常写代码的思路还原的代码(整理后的代码)
#include<stdio.h>
int main(){
int ebp_n=0;
scanf("%d",&ebp_n);
int ebp_arr[100]={0};
for(int ebp_i=0;ebp_i<ebp_n;ebp_i++){
int eax=ebp_i;
scanf("%d",&ebp_arr[ebp_i]);
}
int ebp_sum=0;
for(int ebp_var_1C8=0;ebp_var_1C8<ebp_n;ebp_var_1C8++){
ebp_sum+=ebp_arr[ebp_var_1C8];
}
printf("%d\n",ebp_arr[4]);
printf("%d",ebp_sum);
return 0;
}
运行结果
三、源代码
源代码的意思:输入一个数字n,然后输入n个数字,保存到数组中,输出数组索引为4的元素,并且输出数组所有元素的和,以下为源代码和运行结果