Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
(연관된 글이 2개 있습니다.)

머신 바이트 배열로부터 역어셈블해주는 라이브러리 - Udis86 Assembler

가끔, 기계어로 표현된 바이트 숫자값들로부터 어셈블리 니모닉(mnemonic) 형식을 보고 싶을 때가 있는데요. 이를 위해 인텔에서 제공해주는 문서를 읽고 직접 구현할 수도 있겠지만,

Intel® 64 and IA-32 Architectures Software Developer Manuals
; http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html

역시나 다른 분이 만들어 놓은 라이브러리가 더 좋아 보일 수밖에 없습니다. ^^;

Visual Studio solution to build Netwide Assembler 
; https://github.com/agguro/Nasm-project-vs

비주얼 스튜디오 Team Explorer에서 "https://github.com/agguro/Nasm-project-vs.git" 경로를 clone하고, ".\2.12rc5\NasmProject.sln" 솔루션 파일을 열어 그냥 빌드해 주시면 됩니다.

"Netwide Assembler" 이외에, 라이브러리 형식으로 좀 더 모듈화가 잘 되어 있는 것도 있습니다.

Udis86 Disassembler Library for x86 / x86-64
; http://udis86.sourceforge.net/
; https://github.com/vmt/udis86

그런데, 컴파일을 위해서는 사전 작업을 좀 해야 합니다. 우선, .\BuildVS2010\buildVS2010.bat 파일에서 자신이 가지고 있는 비주얼 스튜디오 버전에 맞게 경로를 수정해 줍니다. (저는 Visual Studio 2015에서 빌드할 것이므로 14.0으로 했습니다.)

echo off
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_amd64

msbuild.exe udis86.sln /t:Clean
msbuild.exe build.proj /t:Clean,BuildRelease_x86,BuildRelease_x64,PostBuild
REM msbuild.exe build.proj /t:Clean,BuildRelease_x86,BuildRelease_x64,BuildDebug_x86,BuildDebug_x64,PostBuild
pause

그다음 Python 2.7이 설치되어 있어야 하는데, 경로가 반드시 c:\python27 이어야 합니다. (다른 곳에 설치했다면 약간의 조정이 필요합니다. 이에 대해서는 .\BuildVS2010\README.txt 파일을 참조하세요.)

Python 2.7 Release
; https://www.python.org/download/releases/2.7/

자, 이제 준비는 끝입니다. 명령행에서 다음과 같이 한번 실행해 줍니다.

.\BuildVS2010> buildVS2010.bat

정상적으로 빌드가 되었다면 이후 ".\BuildVS2010\udis86.sln" 솔루션 파일을 비주얼 스튜디오에서 열어 직접 빌드할 수 있습니다.

포함된 프로젝트는 "libudis86" 정적 라이브러리 유형과 "udcli" 콘솔 프로젝트 유형인데, udcli는 libudis86을 이용한 명령행 프로그램이므로 실제로 우리가 필요한 것은 libudis86입니다. 기본적으로는 정적 .lib를 생성하도록 되어 있는데, 빌드 Configuration을 Debug-DLL(또는 Release-DLL)로 바꾸면 윈도우 동적 .dll로도 만들 수 있습니다.

여기서는 C#에서 좀 더 사용하기 쉽도록 libudis86 정적 라이브러리를 포함하는 Win32 DLL 프로젝트를 별도로 만들어 다음의 함수를 추가적으로 export 하겠습니다.

// http://stackoverflow.com/questions/10737644/convert-const-char-to-wstring
std::wstring s2ws(const std::string& str)
{
    int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
    std::wstring wstrTo(size_needed, 0);
    MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
    return wstrTo;
}

WINLIBUDIS86_API  const wchar_t * __stdcall GetDisassemble(int bitMode, __int64 baseAddress, BYTE *input, int inputLen)
{
    ud_t u;

    ud_init(&u);
    ud_set_input_buffer(&u, input, inputLen);
    
    ud_set_pc(&u, baseAddress);
    ud_set_mode(&u, bitMode);
    ud_set_syntax(&u, UD_SYN_INTEL);

    StringBuilder sb;

    while (ud_disassemble(&u))
    {
        sb.push_back(ud_insn_off(&u), 16);
        sb.push_back(' ');

        wstring txt = s2ws(ud_insn_hex(&u));
        sb.push_back(txt);
        sb.push_back(' ');

        txt = s2ws(ud_insn_asm(&u));
        sb.push_back(txt);

        sb.push_back('\n');
    }

    wstring result = sb.ToString();
    int chLen = result.size();

    int byteLen = (chLen + 1) * sizeof(wchar_t);

    wchar_t *pBuf = (wchar_t *)::CoTaskMemAlloc(byteLen);
    memcpy(pBuf, result.c_str(), byteLen);
    pBuf[chLen] = '\0';

    return pBuf;
}

자... 그럼 이걸 이용해서 지난번에 다룬 MBR의 부트 코드를 덤프해 볼까요? ^^

C#으로 다루는 MBR(Master Boot Record)
; https://www.sysnet.pe.kr/2/0/10913

부트 코드가 16비트 real모드로 0x7c00 주소에 로드되어 실행된다는 점을 기반으로 다음과 같이 인자를 주어 덤프할 수 있습니다. (baseAddress는 0으로 주어도 무방합니다.)

MBR mbr;
bool result = MBR.TryParse(sector, out mbr);

if (result == true)
{
    DumpX86Code(mbr.BootCode);
    foreach (var part in mbr.Partitions)
    {
        Console.WriteLine(part);
    }
}

[DllImport("winlibudis86.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]
static extern string GetDisassemble(int bitMode, long baseAddress, byte[] input, int inputLen);

public void DumpX86Code(byte [] codes)
{
    string txt = GetDisassemble(16, 0x7c00, codes, codes.Length);
    Console.WriteLine(txt);
}

출력 결과는????

7c00 33c0 xor ax, ax
7c02 8ed0 mov ss, ax
7c04 bc007c mov sp, 0x7c00
7c07 8ec0 mov es, ax
7c09 8ed8 mov ds, ax
7c0b be007c mov si, 0x7c00
7c0e bf0006 mov di, 0x600
7c11 b90002 mov cx, 0x200
7c14 fc cld
7c15 f3a4 rep movsb
7c17 50 push ax
7c18 681c06 push 0x61c
7c1b cb retf
7c1c fb sti
7c1d b90400 mov cx, 0x4
7c20 bdbe07 mov bp, 0x7be
7c23 807e0000 cmp byte [bp], 0x0
7c27 7c0b jl 0x7c34
7c29 0f850e01 jnz 0x7d3b
7c2d 83c510 add bp, 0x10
7c30 e2f1 loop 0x7c23
7c32 cd18 int 0x18
7c34 885600 mov [bp], dl
7c37 55 push bp
7c38 c6461105 mov byte [bp+0x11], 0x5
7c3c c6461000 mov byte [bp+0x10], 0x0
7c40 b441 mov ah, 0x41
7c42 bbaa55 mov bx, 0x55aa
7c45 cd13 int 0x13
7c47 5d pop bp
7c48 720f jb 0x7c59
7c4a 81fb55aa cmp bx, 0xaa55
7c4e 7509 jnz 0x7c59
7c50 f7c10100 test cx, 0x1
7c54 7403 jz 0x7c59
7c56 fe4610 inc byte [bp+0x10]
7c59 6660 pushad
7c5b 807e1000 cmp byte [bp+0x10], 0x0
7c5f 7426 jz 0x7c87
7c61 666800000000 push 0x0
7c67 66ff7608 push dword [bp+0x8]
7c6b 680000 push 0x0
7c6e 68007c push 0x7c00
7c71 680100 push 0x1
7c74 681000 push 0x10
7c77 b442 mov ah, 0x42
7c79 8a5600 mov dl, [bp]
7c7c 8bf4 mov si, sp
7c7e cd13 int 0x13
7c80 9f lahf
7c81 83c410 add sp, 0x10
7c84 9e sahf
7c85 eb14 jmp 0x7c9b
7c87 b80102 mov ax, 0x201
7c8a bb007c mov bx, 0x7c00
7c8d 8a5600 mov dl, [bp]
7c90 8a7601 mov dh, [bp+0x1]
7c93 8a4e02 mov cl, [bp+0x2]
7c96 8a6e03 mov ch, [bp+0x3]
7c99 cd13 int 0x13
7c9b 6661 popad
7c9d 731c jae 0x7cbb
7c9f fe4e11 dec byte [bp+0x11]
7ca2 750c jnz 0x7cb0
7ca4 807e0080 cmp byte [bp], 0x80
7ca8 0f848a00 jz 0x7d36
7cac b280 mov dl, 0x80
7cae eb84 jmp 0x7c34
7cb0 55 push bp
7cb1 32e4 xor ah, ah
7cb3 8a5600 mov dl, [bp]
7cb6 cd13 int 0x13
7cb8 5d pop bp
7cb9 eb9e jmp 0x7c59
7cbb 813efe7d55aa cmp word [0x7dfe], 0xaa55
7cc1 756e jnz 0x7d31
7cc3 ff7600 push word [bp]
7cc6 e88d00 call 0x7d56
7cc9 7517 jnz 0x7ce2
7ccb fa cli
7ccc b0d1 mov al, 0xd1
7cce e664 out 0x64, al
7cd0 e88300 call 0x7d56
7cd3 b0df mov al, 0xdf
7cd5 e660 out 0x60, al
7cd7 e87c00 call 0x7d56
7cda b0ff mov al, 0xff
7cdc e664 out 0x64, al
7cde e87500 call 0x7d56
7ce1 fb sti
7ce2 b800bb mov ax, 0xbb00
7ce5 cd1a int 0x1a
7ce7 6623c0 and eax, eax
7cea 753b jnz 0x7d27
7cec 6681fb54435041 cmp ebx, 0x41504354
7cf3 7532 jnz 0x7d27
7cf5 81f90201 cmp cx, 0x102
7cf9 722c jb 0x7d27
7cfb 666807bb0000 push 0xbb07
7d01 666800020000 push 0x200
7d07 666808000000 push 0x8
7d0d 6653 push ebx
7d0f 6653 push ebx
7d11 6655 push ebp
7d13 666800000000 push 0x0
7d19 6668007c0000 push 0x7c00
7d1f 6661 popad
7d21 680000 push 0x0
7d24 07 pop es
7d25 cd1a int 0x1a
7d27 5a pop dx
7d28 32f6 xor dh, dh
7d2a ea007c0000 jmp word 0x0:0x7c00
7d2f cd18 int 0x18
7d31 a0b707 mov al, [0x7b7]
7d34 eb08 jmp 0x7d3e
7d36 a0b607 mov al, [0x7b6]
7d39 eb03 jmp 0x7d3e
7d3b a0b507 mov al, [0x7b5]
7d3e 32e4 xor ah, ah
7d40 050007 add ax, 0x700
7d43 8bf0 mov si, ax
7d45 ac lodsb
7d46 3c00 cmp al, 0x0
7d48 7409 jz 0x7d53
7d4a bb0700 mov bx, 0x7
7d4d b40e mov ah, 0xe
7d4f cd10 int 0x10
7d51 ebf2 jmp 0x7d45
7d53 f4 hlt
7d54 ebfd jmp 0x7d53
7d56 2bc9 sub cx, cx
7d58 e464 in al, 0x64
7d5a eb00 jmp 0x7d5c
7d5c 2402 and al, 0x2
7d5e e0f8 loopne 0x7d58
7d60 2402 and al, 0x2
7d62 c3 ret
7d63 49 dec cx
7d64 6e outsb
7d65 7661 jbe 0x7dc8
7d67 6c insb
7d68 6964207061 imul sp, [si+0x20], 0x6170
7d6d 7274 jb 0x7de3
7d6f 6974696f6e imul si, [si+0x69], 0x6e6f
7d74 207461 and [si+0x61], dh
7d77 626c65 bound bp, [si+0x65]
7d7a 004572 add [di+0x72], al
7d7d 726f jb 0x7dee
7d7f 7220 jb 0x7da1
7d81 6c insb
7d82 6f outsw
7d83 61 popa
7d84 64696e67206f imul bp, [fs:bp+0x67], 0x6f20
7d8a 7065 jo 0x7df1
7d8c 7261 jb 0x7def
7d8e 7469 jz 0x7df9
7d90 6e outsb
7d91 67207379 and [ebx+0x79], dh
7d95 7374 jae 0x7e0b
7d97 656d gs insw
7d99 004d69 add [di+0x69], cl
7d9c 7373 jae 0x7e11
7d9e 696e67206f imul bp, [bp+0x67], 0x6f20
7da3 7065 jo 0x7e0a
7da5 7261 jb 0x7e08
7da7 7469 jz 0x7e12
7da9 6e outsb
7daa 67207379 and [ebx+0x79], dh
7dae 7374 jae 0x7e24
7db0 656d gs insw
7db2 0000 add [bx+si], al
7db4 00637b add [bp+di+0x7b], ah
7db7 9ab5247c03 call word 0x37c:0x24b5
7dbc 0000 add [bx+si], al

(첨부한 파일은 Udis86 라이브러리에 제가 추가한 winlibudis86 Win32 DLL 프로젝트를 추가한 소스코드입니다.)




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 7/10/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 46  47  48  49  50  51  [52]  53  54  55  56  57  58  59  60  ...
NoWriterDateCnt.TitleFile(s)
12320정성태9/11/20209707개발 환경 구성: 512. RDP(원격 데스크톱) 접속 시 비밀 번호를 한 번 더 입력해야 하는 경우
12319정성태9/10/20209465오류 유형: 647. smigdeploy.exe를 Windows Server 2016에서 실행할 때 .NET Framework 미설치 오류 발생
12318정성태9/9/20208996오류 유형: 646. OpenVPN - "TAP-Windows Adapter V9" 어댑터의 "Network cable unplugged" 현상
12317정성태9/9/202011284개발 환경 구성: 511. Beats용 Kibana 기본 대시 보드 구성 방법
12316정성태9/8/20209721디버깅 기술: 170. WinDbg Preview 버전부터 닷넷 코어 3.0 이후의 메모리 덤프에 대해 sos.dll 자동 로드
12315정성태9/7/202011986개발 환경 구성: 510. Logstash - FileBeat을 이용한 IIS 로그 처리 [2]
12314정성태9/7/202010367오류 유형: 645. IIS HTTPERR - Timer_MinBytesPerSecond, Timer_ConnectionIdle 로그
12313정성태9/6/202011682개발 환경 구성: 509. Logstash - 사용자 정의 grok 패턴 추가를 이용한 IIS 로그 처리
12312정성태9/5/202015676개발 환경 구성: 508. Logstash 기본 사용법 [2]
12311정성태9/4/202010833.NET Framework: 937. C# - 간단하게 만들어 보는 리눅스의 nc(netcat), json_pp 프로그램 [1]
12310정성태9/3/202010061오류 유형: 644. Windows could not start the Elasticsearch 7.9.0 (elasticsearch-service-x64) service on Local Computer.
12309정성태9/3/20209791개발 환경 구성: 507. Elasticsearch 6.6부터 기본 추가된 한글 형태소 분석기 노리(nori) 사용법
12308정성태9/2/202011087개발 환경 구성: 506. Windows - 단일 머신에서 단일 바이너리로 여러 개의 ElasticSearch 노드를 실행하는 방법
12307정성태9/2/202011855오류 유형: 643. curl - json_parse_exception / Invalid UTF-8 start byte
12306정성태9/1/20209966오류 유형: 642. SQL Server 시작 오류 - error code 10013
12305정성태9/1/202010912Windows: 172. "Administered port exclusions"이 아닌 포트 범위 항목을 삭제하는 방법
12304정성태8/31/20209856개발 환경 구성: 505. 윈도우 - (네트워크 어댑터의 우선순위로 인한) 열거되는 IP 주소 순서를 조정하는 방법
12303정성태8/30/202010018개발 환경 구성: 504. ETW - 닷넷 프레임워크 기반의 응용 프로그램을 위한 명령행 도구 etrace 소개
12302정성태8/30/20209995.NET Framework: 936. C# - ETW 관련 Win32 API 사용 예제 코드 (5) - Private Logger파일 다운로드1
12301정성태8/30/202010250오류 유형: 641. error MSB4044: The "Fody.WeavingTask" task was not given a value for the required parameter "IntermediateDir".
12300정성태8/29/20209696.NET Framework: 935. C# - ETW 관련 Win32 API 사용 예제 코드 (4) CLR ETW Consumer파일 다운로드1
12299정성태8/27/202010623.NET Framework: 934. C# - ETW 관련 Win32 API 사용 예제 코드 (3) ETW Consumer 구현파일 다운로드1
12298정성태8/27/202010338오류 유형: 640. livekd - Could not resolve symbols for ntoskrnl.exe: MmPfnDatabase
12297정성태8/25/20209516개발 환경 구성: 503. SHA256 테스트 인증서 생성 방법
12296정성태8/24/202010018.NET Framework: 933. C# - ETW 관련 Win32 API 사용 예제 코드 (2) NT Kernel Logger파일 다운로드1
12295정성태8/24/20209362오류 유형: 639. Bitvise - Address is already in use; bind() in ListeningSocket::StartListening() failed: Windows error 10013: An attempt was made to access a socket ,,,
... 46  47  48  49  50  51  [52]  53  54  55  56  57  58  59  60  ...