windows逆向笔记-调用约定、c数据类型、c语言if…else语句
简单函数的反汇编,c语言的调用约定,c语言的数据类型
汇编基础
- ide中的设置
- 寄存器registers、内存地址读取Memory
- 裸函数 void __declspec(naked) function(int x,int y) {ret;}需要自己平栈ret
- 写汇编:__asm{ }
push ebp
mov ebp,esp
push esi
push edi
push ebx
lea edi,dword ptr [ebp-0x40]
mov eax,0xCCCCCCCC
mov ecx,0x10
rep stosd
// ebp+8 第一参数 ebp+0xc第二参数 遵循从右到左入栈
mov eax,dword ptr [ebp+8]
add eax,dword ptr [ebp+0xC]
pop ebx
pop edi
pop esi
mov esp,ebp
pop ebp
ret
调用约定
- __cdecl 参数从右到左入栈,,
谁调用,谁清理堆栈
,调用函数后面加add esp,0x8
,外平栈 - __stdcall 参数从右到左入栈,自己清理堆栈,在调用函数内部平衡,
ret 8
=ret;add exp,0x8
,win32都是这种调用,内平栈 - __fastcall ecx和edx传入前两个参数,后面的参数从右到左入栈,内平栈
判断一个call到底有几个参数:只能一行行分析,结合寄存器和函数返回ret
kernel32()->mainCRTStartup()->main() 程序的入口点,可以通过setting->link->enrty port symbols
控制台程序,入口函数寻找(传入3参数的入口函数):
c语言数据类型
- 基本类型:整数、浮点,数据类型三要素:
- 宽度
- 内存中存储方式、格式
- 作用范围
数据类型 | 比特位 | 字节长度 |
---|---|---|
char | 8bit | 1字节 |
short | 16bit | 2字节 |
int | 32bit | 4字节 |
long | 64bit | 8字节 |
指针 | 32bit | 4字节 |
- 浮点数存储:符号位1位+指数位8位(127+指数然后转化成16进制)+尾数位23位
- 编码:
- 标准ASCII码表每个字符占用一个字节,最大是127,最高位始终为0。扩展ASCII表里面扩展了一些除了一般标点字符等之外的字符
- GB2312衍生自ASCII表,小于127用ASCII表,用2个字节代表一个汉字。
- 内存:
- 代码区 read and write、executable
- 堆栈 arguments参数、局部变量、临时数据
- 堆 动态申请的、大小可变,如malloc()
- 全局变量区 read and write可读可写
- 编译完成以后
内存地址
就不会再变化了 - 全局变量就是所谓的基址
- call中调用以后会被改变
- 找function()的参数个数
- 忽略ebp、esp
- 只找寄存器赋值给地址
- 公式一:寄存器 + ret 4
- 公式二:寄存器 + [ebp+8]+[ebp+0xc]+…
- 编译完成以后
- 常量区 only readable只读
- 函数功能分析
- 分析参数:
ebp+8/ebp+c
或者地址被寄存器赋值的 - 分析局部变量:
ebp-4/ebp-8
- 分析全局变量:类似于
mov dword ptr [0x00421234],eax
- 功能分析:
- 返回值分析:
- 还原成C函数:
- 分析参数:
C语言if…else语句
IF_BEGIN:
先执行各类影响标志位的指令
jxx Else_Begin
…
ELSE_BEGIN:
…
mov eax,dword ptr [ebp+8]
cmp eax,dword ptr[ebp+0xc]
jle function + [0x00421432]
mov edx,dword ptr [ebp+8]
add edx,dword ptr [ebp+0xc]
jmp 0x004215e4
- 分析:
- 每个条件跳转指令要跳转的地址前面都有jmp指令
- 这些jmp指令跳转的地址都是一样的
- 如果某个分支没有条件判断,则为else部分