Windows 逆向-函数指针

Oyst3r 于 2024-01-28 发布

前言

这个主要就是隐藏代码功能,不让那么好逆出来,其它的我真感觉挺鸡肋的,毕竟最终程序实现的功能都一样哈

课堂

基本的定义

这块我感觉也不需要啥理解,反正记住就行,理解也好理解,函数其实也是一个地址,不过这个地址在代码区,大家可以去查看一下反汇编,就是 call 然后后面跟一个地址

int Function(int x,int y){
	return x+y;
}
int main(int argc,char* argv[]){
    int (*pFun)(int,int); //函数指针的声明。函数指针的返回值、名字、参数类型都可以根据自己的意愿来

    pFun = Function;  //但是如果将函数指针指向一个函数,那么此函数的格式必须和此函数指针格式相同,比如返                         回值类型、参数列表等信息都必须相同。因为格式类型都相同了,所以不用强转

    //另一种方式
    pFun = (int (*)(int,int))10;  //也可以使用强转让函数指针指向一个数值,但是这样没有意义,给一个                                      函数的地址才有意义
    return 0;
}

使用

int Function(int x,int y){
	return x + y;
}
int main(int argc,char* argv[]){
    int (*pFun)(int,int);  //声明
    pFun = Function;  //赋值
    int sum = pFun(1,2);  //使用
    printf("%d",sum);  //1+2=3
    return 0;
}

属性探测

编译不通过的具体原因如下

因为函数和我们平时定义的变量是一样的,在内存中都会分配空间,函数中的代码也对应着一堆二进制数,后面学硬编码就知道了,所以函数对应在内存中也是很多二进制数,只不过函数对应的内存在代码区、我们平时定义的变量在全局变量区或者堆栈区等。那么如果定义了不同函数,函数中的内容也不同,此时函数对应的内存宽度是会变化的,即不确定的。而当我们做指针的运算时,会用到函数去掉*号的宽度,比如一个函数指针类型为int (*)(int,int),做运算时要用到去掉一个*号的类型宽度,那么此类型去掉一个*号类型为int (int)(int),即函数对应的内存宽度,但是此时函数对应的内存宽度是无法确定下来的,可能是变化的,所以函数指针做运算时编译是无法通过的

隐藏代码到数据区

比如就把下面这段代码隐藏到数据区

#include "stdafx.h"
int Function(int x,int y){  //看看函数在内存中是什么样的
    return x + y;
}
int main(int argc,char* argv[]){
    Function(1,2);
    return 0;
}

如果这样写的话,反汇编就是 call 什么什么的了

但如果,这么写的话,PS:这个数组里面的东西就是实现这个函数的硬编码,结果就不一样了

#include "stdafx.h"
unsigned char code[] = {  //下面的数据就是Function函数中代码的硬编码
  	0x55,
    0x8B, 0xEC,
    0x83, 0xEC, 0x40,
    0x53,
    0x56,
    0x57,
    0x8D, 0x7D, 0xC0,
    0xB9, 0x10, 0x00, 0x00, 0x00,
    0xB8, 0xCC, 0xCC, 0xCC, 0xCC,
    0xF3, 0xAB,
    0x8B, 0x45, 0x08,
    0x03, 0x45, 0x0C,
    0x5F,
    0x5E,
    0x5B,
    0x8B, 0xE5,
    0x5D,
    0xC3
};
int main(int argc,char* argv[]){
    //因为我们知道我们要隐藏的函数格式是int Function(int x,int y){},所以就按照这种格式声明函数指针
    int (*pFun)(int,int);
    pFun = (int (*)(int,int))&code;  //函数指针指向code数组。这里&code是必需要满足编译器的规范
    int sum = pFun(1,2);  //使用函数指针pFun,来实现调用Function函数的功能
    printf("%d",sum);  //3
    return 0;
}

没点基础的一看就晕了

作业

前两个再上面的和上个笔记就说过了,直接看第三个

#include "stdafx.h"
char data[] = {
	0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x07,0x09,
    0x00,0x20,0x10,0x03,0x03,0x0C,0x00,0x00,0x44,0x00,
    0x00,0x33,0x00,0x47,0x0C,0x0E,0x00,0x0D,0x00,0x11,
    0x00,0x00,0x00,0x02,0x64,0x00,0x00,0x00,0xAA,0x00,
    0x00,0x00,0x64,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x02,0x00,0x74,0x0F,0x41,0x00,0x00,0x00,
    0x01,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0A,0x00,
    0x00,0x02,0x74,0x0F,0x41,0x00,0x06,0x08,0x00,0x00,
    0x00,0x00,0x00,0x64,0x00,0x0F,0x00,0x00,0x0D,0x00,
    0x00,0x00,0x23,0x00,0x00,0x64,0x00,0x00,0x64,0x00
};
int main(int argc,char* argv[]){
    int (*px)[2];   //一维数组指针
    int (*py)[2][3];  //二维数组指针
    char (*pz)[2];  //一维数组指针
	char (*pk)[2][3];  //二维数组指针


    //验证一下
	px = (int (*)[2])data;
	py = (int (*)[2][3])data;
	pz = (char (*)[2])data;
	pk = (char (*)[2][3])data;
    printf("%x\n%x\n%x\n%x\n%x\n%x\n",*(*(px+0)+0),*(*(px+1)+0),*(*(px+2)+3),
           *(*(*(py+1)+2)+3),*(*(pz+2)+3),*(*(*(pk+2)+3)+4));
	return 0;
}

这个就很简单了,直接出结果哇