第一节 1.1C语言
1、注意参数和局部变量在堆栈中的存储方式
2、参数在调用函数前就已经存入堆栈,从[EBP+8]、[EBP+C]、……开始。
3、局部变量是在调用函数后,存入缓冲区里,从[EBP-4]、[EBP-8]、……开始
4、函数运算得到的结果,通常存在EAX里。

 

 

 

第一节 1.2逆向汇编

第一节 1.3练习1
练习1:编写一个函数能够对任意2个整数实现加法,并分析函数的反汇编.
int Plus(int x,int y)
#include <iostream>
#include<Windows.h>
//实现加法功能的函数
int plus(int x,int y)
{
    return x + y;
}
int main()
{
    //调用函数plus();
    plus(1,2);
    system("pause");
}
第一节 1.4练习2
练习2:编写一个函数,能够对任意3个整数实现加法,并分析函数的反汇编(要求使用上一个函数).
int Plus2(int x,int y,int z)
#include "stdio.h"
int plus(int x,int y)
{
    return x+y;
}
int plus2(int x,int y,int z)
{
    int i = plus(x,y);
    return plus(i,z);
}
void main(int argc,char* argv[])
{
    plus2(1,2,3);
}
第一节 1.3练习3
3、编写一个函数,能够实现对任意5个整数实现加法(使用Plus1和Plus2).
并分析一个函数的反汇编代码.
int Plus3(int a,int b,int c,int d,int e)
#include "stdio.h"
int plus(int x,int y)
{
    return x+y;
}
int plus2(int x,int y,int z)
{
    int i = plus(x,y);
    return plus(i,z);
}
int plus3(int a,int b,int c,int d,int e)
{
    int i;
    int r;
    i = plus(a,b);
    r = plus2(c,d,e);
    return i+r;
}
void main(int argc,char* argv[])
{
    plus3(5,6,7,8,9);
}第二节 2.1裸函数与汇编写法
1、裸函数的写法
2、如何在C语言里写汇编代码

声明一个裸函数后,编译器不会生成任何的代码

#include <iostream>
#include<Windows.h>
//构造裸函数
int __declspec(naked) plus(int x,int y)
{    
    __asm
    {
        //提升堆栈
        push ebp
        mov ebp,esp
        sub esp,0x40
        //保护现场
        push edi
        push ebx
        push esi
        //填充缓冲区
        lea edi,dword ptr ss:[ebp-0x40]
        mov ecx,0x10
        mov eax,0xcccccccc
        rep stosd
        //加法功能
        mov eax,[ebp+0x8]
        add eax,[ebp+0xc]
        //恢复现场
        pop esi
        pop ebx
        pop edi
        //降低堆栈
        mov esp,ebp
        pop ebp
        ret
    }
}
int main()
{
    plus(1,2);
    system("pause");
}第二节 2.2调用约定
1、参数是如何传入堆栈?
2、如何平衡堆栈的?
————————————————————————-
调用约定  | 参数压栈  | 平衡堆栈  | 
_cdecl (C和C++默认的调用约定)  | 从右至左  | 调用者清理  | 
_stdcall API使用的调用约定  | 从右至左  | 自身清理  | 
_fastcall  | ecx/edx传送前两个剩下的从右至左  | 自身清理(只有2个参数,不需要内平栈)  | 
————————————————————————
_cdecl
cdecl(C declaration,即C声明)是源起C语言的一种调用约定,也是C语言的事实上的标准。
1.函数实参在线程栈上按照从右至左的顺序依次压栈
2.函数结果保存在寄存器EAX/AX/AL中
3.浮点型结果存放在寄存器ST0中
4.编译后的函数名前缀以一个下划线字符    例:sumExample 编译后:_sumExample
5.调用者负责从线程栈中弹出实参(即清栈)
6.8比特或者16比特长的整形实参提升为32比特长
7.受到函数调用影响的寄存器(volatile registers):EAX, ECX, EDX, ST0 - ST7, ES, GS
8.不受函数调用影响的寄存器: EBX, EBP, ESP, EDI, ESI, CS, DS
9.RET指令从函数被调用者返回到调用者(实质上是读取寄存器EBP所指的线程栈之处保存的函数返回地址并加载到IP寄存器)
10.堆栈平衡是由调用函数来执行的(在call [地址],之后会有add esp x,x表示参数的字节数)

第二节 2.7内联汇编实现功能
/*
-----------------------
-----------------------
编写内联汇编,实现功能
-----------------------
-----------------------
*/
int plus(int x, int y, int z)
{
    int a = 2;
    int b = 3;
    int c = 4;
    return x + y + z + a + b + c;
}答案如下:

#include <iostream>
#include<Windows.h>
#include<stdio.h>
/*
-----------------------
-----------------------
编写内联汇编,实现功能
-----------------------
-----------------------
int plus(int x, int y, int z)
{
    int a = 2;
    int b = 3;
    int c = 4;
    return x + y + z + a + b + c;
}
*/
int __declspec(naked) function(int x, int y, int z)
{
    __asm
    {
        //提升堆栈
        push ebp
        mov ebp,esp
        sub esp,0x40        
        //保护现场
        push edi
        push ebx
        push esi
        //填充缓冲区
        lea edi,dword ptr ss:[ebp-0x40]
        mov eax,0xcccccccc
        mov ecx,0x10
        rep stosd
        //功能实现 
        // return x + y + z + a + b + c;
        //3个参数:(1, 2, 3)
        //3个局部变量:int a = 2  ; int b = 3  ; int c = 4 
        //             [ebp-0x4]  ; [ebp-0x8]  ; [ebp-0xc]
        mov dword ptr ds : [ebp-0x4],2
        mov dword ptr ds : [ebp - 0x8],3
        mov dword ptr ds : [ebp - 0xc],4
        mov eax, dword ptr ds : [ebp + 0x8]
        add eax, dword ptr ds : [ebp + 0xc]
        add eax, dword ptr ds : [ebp + 0x10]
        add eax, dword ptr ds : [ebp - 0x4]
        add eax, dword ptr ds : [ebp - 0x8]
        add eax, dword ptr ds : [ebp - 0xc]
        //还原现场
        pop esi
        pop ebx
        pop edi
        //降低堆栈
        mov esp,ebp
        pop ebp
        //返回
        ret
    }
}
int main()
{
    function(1, 2, 3);
    system("pause");
    return 0;
}
运行验证下:









