Disasm 示例程序改写和适配
简介
用途
可用于反汇编x86的二进制汇编文件,展示出来内部的反汇编原理和流程。
原由
最近在看<<C++ 反汇编与逆向分析技术揭秘>>这本书籍,在第一张的简介中我们可以看到ProViem这个反汇编开源工具的内容,内部介绍了反汇编的基本原理,我们可以看到详细的开源代码。
但是从网址下载后的代码无法直接使用VS2019或者是GNUC工具进行编译构建。主要原因是如下所示:
无法直接构建运行的原因:
-
汇编函数需要用C改写
- 代码中存在__asm关键字,该关键字只能在VS2013前的编译器上编译和识别
- gnuc的gcc/g++是支持asm内建汇编编译的,但是和__asm{}的形式不兼容,需要改写代码。
- 因此为了兼容性,最好是用汇编代码去取代汇编代码部分
-
主函数逻辑存在问题,需要改写
-
本书的随书文件下载网址
改写和适配工具
使用的编译工具
- cmake
- cygwin64(也可用mingw64代替)
- make
- gcc
- g++
- windows平台
汇编代码改写
公用函数和宏定义
#ifdef __GNUC__
// #define _asm __asm__ __volatile__()
#define uint16 unsigned short
#define uint32 unsigned int
#define BigtoLittle16(A) ((((uint16)(A) & 0xff00) >> 8) | (((uint16)(A) & 0x00ff) << 8))
#define BigtoLittle32(A) ((((uint32)(A) & 0xff000000) >> 24) | (((uint32)(A) & 0x00ff0000) >> 8) | \
(((uint32)(A) & 0x0000ff00) << 8) | (((uint32)(A) & 0x000000ff) << 24))
#define LittletoBig16(A) BigtoLittle16(A)
#define LittletoBig32(A) BigtoLittle32(A)
#endif
SwapDword函数
- 作用:从汇编代码来看,就是进行双字在小端/大端序之间的转换
void SwapDword(BYTE *MemPtr,
DWORD *Original,
DWORD *Mirrored)
{
DWORD OriginalDword;
DWORD MirroredDword;
#ifdef __GNUC__
MirroredDword = *((DWORD*)MemPtr);
OriginalDword = LittletoBig32(MirroredDword);
#else
_asm
{
pushad
mov edi,MemPtr
mov eax,dword ptr[edi] // 从MemPtr处获取4个字节,小端存储
mov MirroredDword,eax // 15141312
bswap eax // 镜像bytes
mov OriginalDword,eax // 12131415
popad
}
#endif
*Original = OriginalDword;
*Mirrored = MirroredDword;
return;
}
SwapWord函数
- 作用:从汇编代码来看,就是进行字在小端/大端序之间的转换
void SwapWord(BYTE *MemPtr,
WORD *Original,
WORD *Mirrored)
{
WORD OriginalWord;
WORD MirroredWord;
#ifdef __GNUC__
MirroredWord = *((WORD*)MemPtr);
OriginalWord = LittletoBig16(MirroredWord);
#else
_asm
{
pushad
xor eax,eax
mov edi,MemPtr
mov ax,word ptr[edi]
mov MirroredWord,ax // 1312
bswap eax
shr eax,16
mov OriginalWord,ax // 1213
popad
}
#endif
*Original = OriginalWord;
*Mirrored = MirroredWord;
}
StringToWord函数
- 作用:从汇编代码来看,就是把ascii形式的16进制的hex字符串变成单字的hex二进制数字
WORD StringToWord(char *Text)
{
/*
this function will convert and return
an Hexadecimel String into a real
WORD hex number using assembly directive.
*/
#ifndef __GNUC__
DWORD AsmDwordNum = (DWORD) Text;
#endif
WORD DwordNum = 0;
#ifdef __GNUC__
DWORD edi = 4;
for (DWORD i = 0; i < edi; i++){
char one = Text[i];
char number = 0;
if (one >= 0x30){
if ( one <= 0x39){
// 0~9
number = one - 0x30;
}else{
number = one - 0x37;
}
}else{
number = one;
}
DwordNum += number;
if (i < edi - 1){
DwordNum = (DwordNum << 4);
}
}
#else
_asm
{
PUSHAD
PUSHF
XOR ECX,ECX
XOR EAX,EAX
XOR EDI,EDI
MOV EDI,4H
MOV ESI,AsmDwordNum
_start:
MOV CL,[ESI]
CMP CL,30H
JL _lower
CMP CL,39H
JG _upper
SUB CL,30H
JMP _jmp1
_upper:
SUB CL,37H
JMP _jmp1
_lower:
_jmp1:
ADD EAX,ECX
CMP EDI,1
JZ _out
SHL EAX,4H
_out:
INC ESI
DEC EDI
JNZ _start
MOV DwordNum,AX
POPF
POPAD
}
#endif
return DwordNum;
}
StringToDword函数
-
作用:从汇编代码来看,就是把ascii形式的16进制的hex字符串变成双字的hex二进制数字
-
代码同StringToWord函数差不多,唯一区别就是"DWORD edi = 8;"
main函数
// Disasm_Push.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <string.h>
#include "Decode2Asm.h"
int main()
{
// 假设此字符数组为机器指令编码
unsigned char szAsmData[] = {
0x6A, 0x00, // PUSH 00
0x68,0x00,0x30,0x40,0x00, // PUSH 00403000
0x50, // PUSH EAX
0x51, // PUSH ECX
0x52, // PUSH EDX
0x53 // PUSH EBX
};
char szCode[256] = {0}; // 存放汇编指令信息
unsigned int nIndex = 0; // 每条机器指令长度,用于地址偏移
unsigned int nLen = 0; // 分析数据总长度
unsigned char *pCode = szAsmData;
nLen = sizeof(szAsmData);
while (nLen)
{
if (nLen <= (unsigned int)(pCode - szAsmData)) // 跳出逻辑修改,之前会死循环
{
break;
}
int nAddr = 0 ;
// 解析机器码
Decode2Asm(pCode, szCode, &nIndex, 0);
// 修改pCode偏移
pCode += nIndex; // 跳出逻辑修改,之前会死循环
// 显示汇编指令
puts(szCode);
memset(szCode, 0, sizeof(szCode));
}
return 0;
}
适配cmake和编译工程
cmakelist.txt编写
cmake_minimum_required(VERSION 3.4.1)
project("disasm_exe")
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(MY_BIN_FILE_NAE "disasm_exe")
set(SRC "${CMAKE_SOURCE_DIR}/source")
string(REPLACE "-Os" "-O3" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread -g") #-Wnon-virtual-dtor 检查虚析构函数
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lm -Wextra -flto -fuse-ld=gold")
include_directories(${CMAKE_SOURCE_DIR}/include)
include_directories(${SRC})
aux_source_directory(${SRC} SRC_LIST)
ADD_EXECUTABLE(${MY_BIN_FILE_NAE}
${SRC_LIST}
)
target_link_libraries(${MY_BIN_FILE_NAE}
${dl-lib}
)
windows上使用cmake调用gcc/g++工具编译
rd /s /q build
mkdir build
cd build
cmake .. -G "Unix Makefiles" -D CMAKE_CXX_COMPILER=D:/Program/cygwin64/bin/g++.exe -D CMAKE_C_COMPILER=D:/Program/cygwin64/bin/gcc.exe -D CMAKE_MAKE_PROGRAM=D:/Program/cygwin64/bin/make.exe
make -j32
整个工程下载
- 具体可见下载地址