骚操作:隐藏代码到数据区,函数指针【滴水逆向三期37笔记】

文章目录

      • 引言
      • 函数指针
            • 1.简单了解函数指针
            • 2. 函数指针的声明:
      • 隐藏代码到数据区的“骚”操作

引言

指针被称为C语言的灵魂,也是令许多初学者头疼的地方,在前一章节中我们讲解到了多级指针,从反汇编角度带大家了解了指针,如果对指针不是很熟悉的话,大家可以取看一看:http://t.csdn.cn/Qw5oi,这一章节来带大家了解函数指针,并且为大家介绍函数指针的一个利用:将代码隐藏到数据区。
我们在正向开发的过程中如果设计了一个功能函数,并且不想他人轻易地通过反汇编来得到我们功能函数的代码,那么我们可以通过将代码隐藏到数据区,这是一种简单的“加密”方式。

函数指针

在学习隐藏代码到数据区之前,我们首先来学习函数指针,因为我们如果要调用隐藏在数据区的函数的话,我们需要通过函数指针来完成。

1.简单了解函数指针

通过函数指针,我们可以做到为一个函数起别名:
例如:

#include
int add(int a,int b);
int main(int argc, char* argv[])
{
	printf("%d",add(3,4));
	return 0;
}
int add(int a,int b){
	return a+b;
}

在编译运行后我们观察到终端输出了7。我们再来通过函数指针来调用该函数(这里定义函数指针的方法接下来为大家介绍,这里看我操作就OK):

#include
int add(int a,int b);
int main(int argc, char* argv[])
{
	int(*sub)(int,int);
	sub=&add;
	printf("%d",sub(3,4));
	return 0;
}
int add(int a,int b){
	return a+b;
}

这里我们定义一个指针函数,并且把add函数的地址给到函数指针(注意指针类型,如果类型不同,可以通过强制转型进行赋值。
我们通过函数指针sub来调用add函数,发现终端还是输出7。

2. 函数指针的声明:

函数指针的声明方式为:

返回值类型(*函数名)(参数表)

在这里我们拿前面为函数起别名的代码举一个例子:
add函数返回值为int类型,参数表中有两个int类型的数据,那么我们在声明函数指针时,可以这样声明:

int(*sub)(int,int)

在前一张的学习中我们也了解到指针类型在内存中国都是占据4个字节。

隐藏代码到数据区的“骚”操作

在我们逆向学习的过程中,我们知道有些程序是被加了“壳”的,为逆向分析带来了许多困难,而这里的隐藏代码到数据区,如果代码较多,也能为逆向分析带来些许困难,实现对函数的“加密”。
接下我们就来了解一下将代码隐藏到数据区的“骚”操作:
首先来看看没有隐藏的源代码:

#include
int add(int a,int b);
int main(int argc, char* argv[])
{
	printf("%d",add(3,4));
	return 0;
}
int add(int a,int b){
	return a+b;
}

我们来到反汇编:

55                   push        ebp
8B EC                mov         ebp,esp
83 EC 40             sub         esp,40h
53                   push        ebx
56                   push        esi
57                   push        edi
8D 7D C0             lea         edi,[ebp-40h]
B9 10 00 00 00       mov         ecx,10h
B8 CC CC CC CC       mov         eax,0CCCCCCCCh
F3 AB                rep stos    dword ptr [edi]
8B 45 08             mov         eax,dword ptr [ebp+8]
03 45 0C             add         eax,dword ptr [ebp+0Ch]
5F                   pop         edi
5E                   pop         esi
5B                   pop         ebx
8B E5                mov         esp,ebp
5D                   pop         ebp
C3                   ret

这里是add函数的反汇编代码和硬编码,我们将这里的硬编码放入一个数组中:

#include 
int main(int argc, char* argv[])
{
	char add[] = {
	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 (*sub)(int,int);
    sub = (int (__cdecl *)(int,int))&add;
    printf("%d\n",sub(3,4));
    return 0;
}
};

这样隐藏后,在反汇编窗口就无法直接找到add函数了,必须通过数组地址,找到硬编码,再将会硬编码转换至汇编进行分析,在非常庞大的数据量下寻找硬编码也是比较困难的,这样就能做到对代码的很好的隐藏(在计算机看来,代码和数据并无两样,计算机只负责存储)。
通过编译运行我们能够在程序终端看到仍然输出7,可以确定将代码隐藏进了数据区,这里实际上是将硬编码存储进了数据区。
OK今天的总结就到这里,在滴水逆向三期的视频中接下来的两节分别为位运算和内存分配,文件读写,我们就不在博客中介绍了,下一节我们就将进入逆向的入门学习:PE头解析。
最后,非常希望大家可以指出此篇笔记的不足或者错误之处,当然希望我们能够共同学习,共同进步!!!

你可能感兴趣的:(PE文件结构学习,c语言,安全,windows,c++)