Disasm 示例程序改写和适配

Disasm 示例程序改写和适配

简介

用途

可用于反汇编x86的二进制汇编文件,展示出来内部的反汇编原理和流程。

原由

最近在看<>这本书籍,在第一张的简介中我们可以看到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 
#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

整个工程下载

  • 具体可见下载地址

你可能感兴趣的:(ASM,mfc,c++,汇编)