博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
逆向分析技术
阅读量:4982 次
发布时间:2019-06-12

本文共 3919 字,大约阅读时间需要 13 分钟。

1 . 函数参数传递

调用约定 _cdecl _stdcall  _fastcall
传参顺序 左->右 右->左 寄存器和堆栈传参
平衡堆栈者 调用者 子程序 子程序
int _cdecl Add(char a, long b, int c, int d){return (a + b + c + d);}

push 4

push 3
push 2
push 1
call Add (1161A60h)
add esp,10h //调用者平衡堆栈

int _stdcall Add(char a, long b, int c, int d){    return (a + b + c + d);}

push 4 

push 3 
push 2 
push 1 
call Add (1161A60h) //子程序Add里面平衡堆栈

 

 

int _fastcall Add(char a, long b, int c, int d){return (a + b + c + d);}

push 4

push 3
mov edx,2 //寄存器传参
mov cl,1 //寄存器传参
call Add (11F1A60h) //子程序Add里面 平衡堆栈

_fastcall调用约定不同编译器传参不同:
1. MS VC: 最左边2个参数依次 ecx, edx
2. borland delphi/C++:最左边2个参数 eax, edx,ecx
3. watcom C: 最左边2个参数 eax, edx,ebx,ecx
4. 剩下的参数的全部esp传参

thiscall 也是寄存器传递参数, C++非静态成员函数的默认调用约定,
对象的每个成员函数隐含接受this指针。通过ecx传递this指针

class CSum{public:int Add(int a, int b){return (a + b);}};void ClllDlg::OnBnClickedOk2(){CSum sum;sum.Add(1, 2);}

push 2

push 1
lea ecx,[sum]
call CSum::Add (1221B10h)

2. 函数返回值:

2.1函数返回值一般在eax中,如果返回值超过了eax容量,高32位存放在edx中

2.2.通过参数按传引用的方式返回值

以下代码就是通过参数按传引用的方式返回值

void max(int *a, int *b);
int main( )
{
int a=5,b=6;
max(&a, &b);
printf("a、b中较大的数是%d",a); //将最大的数显示出来
return 0;
}
void max( int *a, int *b)
{
if(*a < *b)
*a=*b; //经比较后,将较大的数放到a变量之中
}

 

3. 局部变量

3.1.利用堆栈存放局部变量,分配局部变量空间

形式1: 形式2:   形式3: 
sub esp, n
add esp, n
add esp,-n
sub esp, -n

push reg

pop reg

 

参数相对于 ebp是正的

局部变量相对于 esp是负的

 

3.2.利用寄存器存放局部变量

 除了堆栈存放 局部变量外,6个通用寄存器也可以存放局部变量。

 

4. 全局变量

1. 全局变量一般存放在.data区块, 它是一个固定值,采用硬编码方式
mov dword ptr [4944A0h],7 //4944A0h就是全部变量的地址
mov eax,dword ptr [b]

 

5. 数组

5.1. 数组是连续数据的集合,汇编下访问数组是基址+变量的形式访问

#include 
int main(void){static int a[3]={
0x11,0x22,0x33};int i,s=0,b[3];for(i=0;i<3;i++){ s=s+a[i];b[i]=s;}for(i=0;i<3;i++){printf("%d\n",b[i]);}return 0;}

mov eax,dword ptr [i]

mov ecx,dword ptr [s]
add ecx,dword ptr a (493078h)[eax*4]//493078h数组基址

 

 6.虚函数

虚函数是在程序运行时刻定义的函数, 虚函数的地址不能在编译时刻确定,所以虚函数引用

通常放在一个专有数组里-虚函数表(VTBL), 每一个虚函数对象都具有虚函数表指针(VPTR),
虚函数通过指向虚函数表的指针间接调用。

#include 
class CSum{public: virtual int Add(int a, int b) { return(a + b); } virtual int Sub(int a, int b ) { return(a - b); }};void main(){ CSum* pCSum = new CSum ; pCSum->Add(1,2); pCSum->Sub(1,2);}

  

.text:00401000 ; int __cdecl main(int argc, const char **argv, const char **envp)

.text:00401000 _main proc near ; CODE XREF: start+AFp
.text:00401000
.text:00401000 argc = dword ptr 4
.text:00401000 argv = dword ptr 8
.text:00401000 envp = dword ptr 0Ch
.text:00401000
.text:00401000 push esi
.text:00401001 push 4
.text:00401003 call ??2@YAPAXI@Z ;new为创建对象分配4个字节
.text:00401008 add esp, 4
.text:0040100B test eax, eax
.text:0040100D jz short loc_401019
.text:0040100F mov dword ptr [eax], offset off_4050A0 ;将4050A0写入创建对象的实例中,4050A0是虚函数表的指针。
.text:00401015 mov esi, eax
.text:00401017 jmp short loc_40101B
.text:00401019 ; ---------------------------------------------------------------------------
.text:00401019
.text:00401019 loc_401019: ; CODE XREF: _main+Dj
.text:00401019 xor esi, esi
.text:0040101B
.text:0040101B loc_40101B: ; CODE XREF: _main+17j
.text:0040101B mov eax, [esi]
.text:0040101D push 2
.text:0040101F push 1
.text:00401021 mov ecx, esi
.text:00401023 call dword ptr [eax]
.text:00401025 mov edx, [esi]
.text:00401027 push 2
.text:00401029 push 1
.text:0040102B mov ecx, esi
.text:0040102D call dword ptr [edx+4]
.text:00401030 pop esi
.text:00401031 retn
.text:00401031 _main endp

查看虚函数表 4050A0的数据

004050A0 40 10 40 00 50 10 40 00 FF FF FF FF 2E 11 40 00 @.@.P.@.......@.
004050B0 42 11 40 00 5F 5F 47 4C 4F 42 41 4C 5F 48 45 41 B.@.__GLOBAL_HEA

VTBL的2组数据

[VTBL] = 401040h
[VTBL+4] = 401050h
进一步看看这2个指针的内容

sub_401040 proc near

arg_0= dword ptr 4
arg_4= dword ptr 8
mov eax, [esp+arg_4]
mov ecx, [esp+arg_0]
add eax, ecx
retn 8
sub_401040 endp

sub_401050 proc near
arg_0= dword ptr 4
arg_4= dword ptr 8
mov eax, [esp+arg_0]
mov ecx, [esp+arg_4]
sub eax, ecx
retn 8
sub_401050 endp

原来 虚函数是通过虚函数表的指针 间接调用

 

转载于:https://www.cnblogs.com/mayingkun/p/6060410.html

你可能感兴趣的文章
java基础二 分支循环
查看>>
python--002--数据类型(list、tuple)
查看>>
把近期的小错误整理一下
查看>>
动态规划 —— 背包问题一 专项研究学习
查看>>
51nod 1571 最近等对 | 线段树 离线
查看>>
关于parseInt的看法
查看>>
从用户端到后台系统,严选分销教会我这些事
查看>>
数据分析融入至BI工具的新思路
查看>>
c#必会知识点
查看>>
网页使用MD5加密
查看>>
JS 基础
查看>>
HBase shell 中的十六进制数值表示
查看>>
Python3 中 configparser 模块解析配置的用法详解
查看>>
新手android环境搭建、debug调试及各种插件安装__图文全解
查看>>
未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序 win2008R2 X64 IIS7.5
查看>>
Diffuse贴图+Lightmap+Ambient
查看>>
矩阵树定理
查看>>
[算法]Evaluate Reverse Polish Notation
查看>>
go语言之进阶篇接口的定义和实现以及接口的继承
查看>>
SmartPhone手机网站的制作
查看>>