c语言02_数据类型上

 

一、c是怎么变成汇编的

1、裸函数是编译器不管的

⑴写一个空函数(里面什么都不写),f7f5打开反汇编

f11打开jmp

什么都没写里面还是有一大堆(是编译器和连接器做的)

⑵裸函数

f7f5查看反汇编找到调用的函数0040D708

f11打开

再f11打开,里面一行汇编代码都没有

①空函数

f7f5

运行后不进反汇编,先f10一行一行运行

运行至最后一行没有出错,证明空函数

②裸函数

f7f5

f10,出错

③原因

1️⃣将空函数打开反汇编看

call将0040D72D压入堆栈和把eip地址改到call后面0040101e

 f11后再f11

一直f10到0040D70e,return后回到③的第一张图

可以调用空函数是因为里面生成了return,可以返回

2️⃣打开裸函数

也有call(作用和空函数里面的一样)

f11再f11,只有int3(相当于断点,程序执行到这就会停下来)

3️⃣如果想让裸函数运行,可以再c里面写汇编

__asm{}                               (最好是两个_)

f7f5再f11f11    有ret可以返回,就能执行

 2、在裸函数里面实现一个加法

asm里面内容

 

 二、调用约定:参数的传递顺序

 

1、_cdecl:c/c++默认的调用约定(写不写都相当于写了)

从后往前压,外平栈

参数从后往前压栈,谁调用00400D79C这个函数谁负责平衡堆栈,add esp,8是在外面平衡堆栈(是在主函数叫外平栈)

 2、_ stdcall:

也是从后往前压,内平栈

 f10运行到00400D79C,f11进入函数再f11,再一行一行的运行到ret

一般只有一个ret,而这一行是ret 8,就相当于是add esp,8

这种是在子函数里面,叫内平栈

 3、_fastcall:用两个寄存器,传递速度快(不超过两个参数 ),还是从右到左

之前add是因为的是push了两个数 占用了8个字节,esp的值需要往上压8个字节

而mov是用两个寄存器传的值

f11打开进去看里面只有一个ret

 传2个参数改成传4个

他前两行也是用的push,

 进入函数,是ret 8

 (逆向中不能根据ret8就判断是两个参数,可能是cdecl或stdcall,也可能是fastcall中4个参数有两个寄存器) 

例外:如何区分一个call有几个参数

①根据函数调用:

错误判断:看有没有add,看call上面的值

 有可能push 4是在plus4里面没用是在pop里面用的

有可能0040D836以上的值不一定是给此行的call用的可能是给下一个的

正确判断:一行一行分析再结合参数调用和堆栈平衡的代码

三、callingconventionr入口 

 

1、修改入口例:随便写一个空函数,f7f5打开,旁边有一个call stack

 第一个main是我们的程序,最后一行的KERNEL32那一行调用了mainCRTStartup这个方法而这个又调用了我们写的main程序

 自己写的代码入(即callstack中第一个main)口不是真正程序入口

真正程序的入口是mainCRTStartup

 ------------------------------------------分割线---------------------------------------------

改入口点

 

 打开setting,选择link,选output,entry-point symbol改成test

 

 改了之后运行到void tset就不走了

2、找入口方法:找调用的函数后面有三个参数的

找到一个调用函数

push了三个参数,后面是add esp,0c;如果是两个参数平衡堆栈是add8,而0c是三个参数

 进add里面观察:

 (一)0:保存栈底

(二)1-3:提升堆栈

(三)6-8:保留控制台环境

(四)9-6:往缓冲区写内容

(五)8-8:有一个函数里面有5个参数三个push两个mov,调用函数是fastcall

①call进去

 a、进第一个函数4DFFFFFF看传了多少个参数,打开看到ret0c,是传了三个参数也是内平衡,是stdingcall

b、24FFFFFF:前面有两个push和add8且是外平衡,是cdecl

c、11FFFFFF:与b中的地址一样

 

posted @ 2025-03-18 19:33  Auriry  阅读(11)  评论(0)    收藏  举报