⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 me.txt

📁 将exe等可执行文件转化成c程序的反编译程序,先到汇编再到c
💻 TXT
📖 第 1 页 / 共 2 页
字号:
	VAR		var_r2;
	DWORD	i1;	// =4, 当type == i_Address时,[eax+ebx*4+8888]
	DWORD	i2;	// =8888
};

这个结构INSTR中明确了一条伪码可以有3个操作量,var_w是写操作数,var_r1和var_r2是两
个读操作数。因为INSTR与XCPUCODE结构的不同,在从XCPUCODE到INSTR的转化中,可能会出
现一条指令变成两条甚至多条的情况。比如
        mov eax, [ebx+ecx*4+1000]
会变成
        i_GetAddr var_w=tem_1, var_r1=EBX, var_r2=ECX, i1=4, i2=1000
        i_Readpointto var_w=eax, var_r1=tem_1
会产生一个中间变量tem_1
再比如
        push eax
会变成
        i_Assign tem_1, eax
        i_Sub    esp, 4

3. 变量的优化
变量优化是exetoc的主要技术点。
3.1 取变量特征串
以下代码是返回一条指令是如何使用一个变量的:
    if (the->bJxx)
        return 'J';

    PINSTR pinstr = the->pinstr;
    BYTE rw = the->rw;
    if (pinstr->type == i_Label) return 'L';
    if (pinstr->type == i_Return) return 'E';
    if (pinstr->type == i_Assign)
    {
        if (rw == 1) return '5';    //Read
        if (rw == 2) return '6';    //Write
        if (rw == 3) return '7';    //Read and Write
    }
    else
    {
        if (rw == 1) return '1';    //Read
        if (rw == 2) return '2';    //Write
        if (rw == 3) return '3';    //Read and Write
    }
也就是说,由几个字母表示了指令对一个变量的使用方法,
有"JLE567123"种可能。J代表一个跳转,L代表一个label即跳转目的,
E代表函数结束,1读2写3是读写。5代表赋值给另外一个量,6代表把另一个
量赋值给我。
这样,一个函数中如何使用一个变量的,就用一个字串表示出来了。
对字串的处理总是简单易懂的。

实际的情况要复杂得多。这样直接得到的特征串常常意义不大。还需要简化。
比如
        2JL1E
就是“写-跳-标-读-End”就可以简化为 21E
再比如
        ebx = 0
        ? = ebx
        while (?)
        {
           ebx = ?
           ? = ebx
        }
        return
对变量ebx来说,特征串是 65LJ65JLE
容易理解这个特征串可以简化为 6565E




3.2 根据变量特征串进行变量优化
比如我们遇到了一个特征串是:
        61E
即一个变量被赋值,使用了一次,就结束了。则一般情况下,可以把它“消”
掉,即直接使用赋值的源变量。

3.3 根据变量特征串进行变量分离
比如我们遇到了一个特征串是:
        211211E
显然这可以分为两个变量。
分离变量是后面数据类型分析的基础。
比如一个寄存器ecx在一个函数中有多次使用,每次之间
并无联系,我们就不能认为它是一个变量,而应该分为ecx1,ecx2,ecx3等等。变量分离
以后,才好给它们加数据类型。

4. 标准C++头文件解析
已经基本支持一般的头文件,支持//注解,/**/注解,#define,typedef,函数预定义,
struct,enum,class等

5. 标准库函数解析
现在是读取vc的LIB文件,从中解析出一个个的标准函数,生成自己的标识文件。分析时
进行全比较。要注意重定位项。

6. 流程分析
char finger_for[] 	= "0_jmp1_from2_0_from1_0_jxx3_0_jmp2_from3_";
char finger_if [] 	= "0_jxx1_0_from1_";
char finger_if_else[] = "0_jxx1_0_jmp2_from1_0_from2_";
char finger_while[] 	= "from1_0_jxx2_0_jmp1_from2_";
char finger_dowhile[] = "from1_0_jxx1_";

7. 数据类型分析
表示数据类型的结构:
enum VarTT
{
    vtt_unknown = 0,
        vtt_base	= 1,	//	是基类型,不依赖于其它类型
        vtt_signed,			//	缺省为unsigned
        vtt_typedef,
        vtt_array,			//	数组
        vtt_point,
        vtt_class,          // 结构,或类
        vtt_funcpoint,
        vtt_const,			//	const
        vtt_enum,
    vtt_simple,         // 如果不知道是什么类型,就用这个
                        //简单类型 对每一个size都会有一个简单类型,实际上未知类型。名叫bit8之类
};

struct SVarType
{
	VarTypeID	id;			//	如果谁需要这个结构,只要记下这个id就行了
							//	通过这个id与 SVar 联系
	VarTT	type;

	union
	{
		struct
		{
			CFuncType*		pFuncType;		//	for vtt_funcpoint, if this is a func pointer
		} m_funcpoint;						//	= 1 means unknown funcpoint
		struct
		{
			char	classname[80];		//!!! only for unknown struc !
			Class_st*		pClass;			//	if this is a class
		} m_class;
		struct
		{
			VarTypeID	id_pointto;	//	if this is a pointer
		} m_point;
		struct
		{
			SIZEOF	arraynum;		// 	if this is a array, this is item count
			VarTypeID	id_arrayitem;	//	if this is a array, this is item id
		} m_array;
		struct
		{
			VarTypeID	id_base;	//	这个数据类型的基类
			PSTR	name;
		} m_typedef;
		struct
		{
			VarTypeID	id_base;	//	这个数据类型的基类
		} m_const;
		struct
		{
			VarTypeID	id_base;	//	这个数据类型的基类
			PSTR	name;
		} m_signed;
		struct
		{
			SIZEOF	opsize;
			PSTR	name;
		} m_base;					//	基类型
        struct
        {
            SIZEOF  opsize;
        } m_simple;
		struct
		{
			char	enumname[80];
			enum_st*	m_penum;
		} m_enum;
	};
};
注意其中的vtt_simple。每一个变量初始化的时候,都根据它的sizeof给它一个vtt_simple
类型的数据类型。意思是它的数据类型为未知。如果在代码中遇到一个api call,则可以
根据我们事先从标准头文件中得到的该api的函数预定义,获得它的各参数数据类型,及
返回值数据类型。并由此类推,得到其它变量的数据类型。比如遇到一个
        i_Assign B, A
如果已经B的数据类型是HWND,而A的数据类型是vtt_simple,则可以放心地把A的数据类型
也置为HWND.
再比如,
        i_ReadPointto B,A
如果已经B的数据类型是char,而A的数据类型是vtt_simple,则可以放心地把A的数据类型
也置为char*.

typedef const char * PCSTR;


8. 未知指令的处理(未实现)

input edi
xor eax, eax
or ecx, -1
repnz scasb
not ecx
dec ecx
mov eax, ecx
----------
edi = ?
eax = 0
ecx = -1
??? repnz scasb
ecx = ?(ecx)
ecx = ecx -1
mov eax, ecx
-----------
edi = ?
eax = 0
ecx = -1
unknow(write ecx, edi read al, edi[])
ecx = ?(ecx)
ecx = ecx -1
mov eax, ecx
------
edi = ?
eax = 0
ecx = -1
unknow
{
    read_write ecx
    read_write edi
    read edi[]
    read al
}

ecx = ?(ecx)
ecx = ecx -1
mov eax, ecx
------
edi = ?
unknow
{
    read_write edi
    read edi[]
    write ecx
    write eax
}
mov eax, ecx
-----------
edi = ?
unknow
{
    read edi
    write ecx
}
mov eax, ecx
-----------
edi = ?
ecx = unknown_math(edi);
mov eax, ecx
-----------

9。实例:

=============================文章结束================================


PUSH   -01
PUSH   00406CB8
MOV    EAX,FS:[00000000]
PUSH   EAX
MOV    FS:[00000000],ESP
SUB    ESP,+08
...
MOV    DWORD PTR [ESP+10],00000000
...
MOV    DWORD PTR [ESP+10],FFFFFFFF
...
MOV    ECX,[ESP+08]
MOV    FS:[00000000],ECX
ADD    ESP,+14
RET
-----------------------    
PUSH   -01
PUSH   00406CB8
MOV    EAX,FS:[00000000]
PUSH   EAX
MOV    FS:[00000000],ESP
...
MOV    DWORD PTR [ESP+8],00000000
...
MOV    DWORD PTR [ESP+8],FFFFFFFF
...
MOV    ECX,[ESP]
MOV    FS:[00000000],ECX
ADD    ESP,+0c
RET

_EH_prolog
CxxThrowException

call    _EH_prolog
的意思是 mov ebp, esp

_CxxThrowException 是 __stdcall 8





⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -