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{pushadmov edi,MemPtr mov eax,dword ptr[edi] // 从MemPtr处获取4个字节,小端存储mov MirroredDword,eax // 15141312bswap eax // 镜像bytesmov 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{pushadxor eax,eaxmov edi,MemPtrmov ax,word ptr[edi]mov MirroredWord,ax // 1312bswap eaxshr eax,16mov OriginalWord,ax // 1213 popad}
#endif*Original = OriginalWord;*Mirrored = MirroredWord;
}
StringToWord函数
- 作用:从汇编代码来看,就是把ascii形式的16进制的hex字符串变成单字的hex二进制数字
WORD StringToWord(char *Text)
{/*this function will convert and returnan Hexadecimel String into a realWORD hex number using assembly directive.*/
#ifndef __GNUC__DWORD AsmDwordNum = (DWORD) Text;
#endifWORD 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~9number = one - 0x30;}else{number = one - 0x37;}}else{number = one;}DwordNum += number;if (i < edi - 1){DwordNum = (DwordNum << 4);}}
#else_asm{PUSHADPUSHFXOR ECX,ECXXOR EAX,EAXXOR EDI,EDIMOV EDI,4HMOV ESI,AsmDwordNum_start:MOV CL,[ESI]CMP CL,30HJL _lowerCMP CL,39HJG _upperSUB CL,30HJMP _jmp1_upper:SUB CL,37HJMP _jmp1_lower:_jmp1:ADD EAX,ECXCMP EDI,1JZ _outSHL EAX,4H_out:INC ESIDEC EDIJNZ _startMOV DwordNum,AXPOPFPOPAD}
#endifreturn 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 000x68,0x00,0x30,0x40,0x00, // PUSH 004030000x50, // PUSH EAX0x51, // PUSH ECX0x52, // PUSH EDX0x53 // 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
整个工程下载
- 具体可见下载地址