#INCLUDE "NFO.h"
#INCLUDE "DISCLAIMER.h"
USING NAMESPACE REVERSE_ENGINEERING

char szTajuk[]		= "TooLZ Of The Trade [Part 2]"
char szPenulis[]	= "Ancient One"
char szWeb[]		= "http://www26.brinskter.com/paipx"
char szMod[]		= "+n +g"


VOID MAIN () {

Pada part pertama saya dah bincangkan mengenai debugger. Bagaimana anda boleh mengubah sesuatu program tersebut dengan menggunakan debugger dan menyaksikan bagaimana program itu dilaksanakan arahan demi arahan secara langsung di dalam debugger. Di masa akan datang saya akan meneruskan dengan tutorial mengenai debugger since ia amat penting dalam cracking activity. Kali ini saya akan membincangkan pula mengenai satu lagi tools yang penting dalam aktiviti ini, iaitu disassembler.

DISASSEMBLER.
Secara basicnya, fungsi disassembler dan debugger sama sahaja. Ia akan keluarkan disassembly output bagi program tersebut. Akan tetapi, berbanding dengan debugger, disassembler tidak melaksanakan atau mengawal program tersebut, sebaliknya cuma menghuraikan kembali nombor2 binari dalam program tersebut kepada kod2 assembly yang sepadan. Dengan disassembler, program tersebut akan dianalisis dari byte pertama hingga akhir dan keseluruhan assembly code untuk program tersebut akan dikeluarkan. Dengan debugger, kita boleh berinteraksi dengan kod2 di dalam program tersebut, ini yang kita panggil sebagai live approach. Dengan disassembler kita cuma mempunyai kod program tersebut dalam assembly tetapi tidak boleh berinteraksi dengannya pada masa itu juga. Ini yang kita panggil sebagai dead-list approach.

Terdapat banyak jenis disassembler bergantung pada keupayaannya. Disassembler yang baik akan membenarkan analisis format fail, struktur kod dan mengeluarkan output untuk pemproses yang dikehendaki. Pengesanan format fail amat penting kerana terdapat beberapa format fail yang berbeza digunakan dalam pelbagai platform. Dalam Windows, format fail terbaru untuk executable ialah PE (Portable Executable). Sebelumnya ialah NE (New Executable) akan tetapi ia tetap disokong oleh platform Windows terbaru. Dengan penganalisaan format fail, disassembler berupaya mengeluarkan output disassembly yang betul seperti program entry point, mengeluarkan maklumat export dan import table daripada program dan juga tidak mengeluarkan disassembly untuk seksyen2 yang tidak berkenaan. Ini kerana executable file terdiri daripada sections seperti data, kod, resource, dan sebagainya. Jadi jika disassembler berupaya membezakan dan menganalisa format file ini, kod disassembly yang betul dan optimum mampu dikeluarkan.

Berbeza dengan disassembler yang hanya mengeluarkan disassembly program tersebut secara membuta tuli, disassembler yang bijak juga mampu mengenali compiler program tersebut berdasarkan signature bytes dalam program tersebut. Ia juga mampu untuk mengenali loop seperti c language for loop, while, do..while, if..else if.. dan sebagainya sekaligus menukarkan kod assembly kepada c. Ini banyak membantu kita dalam menganalisa sesuatu program tersebut bukan pada masa nyata.

Bergantung kepada keperluan anda, debugger dan disassembler masing-masing mempunyai kelebihannya sendiri. Apa yang penting adalah mencari debugger atau disassembler yang bagus. Terdapat banyak disassembler yang bagus boleh didapati di internet dan di antaranya ialah W32DASM, IDA Pro, HIEW dan sebagainya. Jika anda hendak mengetahui mana satukah yang terbaik, just download them all dan try satu persatu. Secara personal, saya sukakan HIEW dan W32DASM. Saya cuma gunakan IDA Pro untuk program yang bersaiz besar. Untuk mengetahui bagaimana disassembler berfungsi, mari kita lihat satu program PE yang telah di'disassemble' di dalam W32DASM. Pertama sekali saya tunjukkan kod sumber di dalam assembly yang telah dikompil dengan Microsoft MASM :

	;main.asm test program for disassembler
	;$ml /c /Cp /coff main.asm
	;$link /SUBSYSTEM:WINDOWS main.obj

	.386
	.MODEL FLAT, STDCALL
	OPTION CASEMAP:NONE

	include ..\..\include\windows.inc
	include ..\..\include\user32.inc

	includelib ..\..\lib\user32.lib

	.DATA
	szIsi	BYTE	"Hello World!", 0
	szTajuk BYTE	"Test", 0

	.CODE

	mula :
	
		INVOKE	MessageBox, 0, OFFSET szIsi, OFFSET szTajuk, MB_OK
		RET

	end mula

Ini kod yang teringkas saya boleh fikirkan yang keluarkan message box. Ini adalah program Windows yang valid, selepas sahaja message box di'invoke', kita letakkan ret so ia kembali kepada operating system (program kita exit). Jika anda hendak compile program di atas, anda perlu mengubah include dan includelib supaya ia boleh mencarinya di dalam sistem anda. Kod ini dicompile oleh MASM v7.0. Di bawah pula ialah kod yang dikeluarkan oleh W32DASM :

Disassembly of File: C:\Developments\MASM32\Projects\New Folder\main.exe
Code Offset = 00000400, Code Size = 00000200
Data Offset = 00000800, Data Size = 00000200

Number of Objects = 0003 (dec), Imagebase = 00400000h

   Object01: .text    RVA: 00001000 Offset: 00000400 Size: 00000200 Flags: 60000020
   Object02: .rdata   RVA: 00002000 Offset: 00000600 Size: 00000200 Flags: 40000040
   Object03: .data    RVA: 00003000 Offset: 00000800 Size: 00000200 Flags: C0000040


+++++++++++++++++++ MENU INFORMATION ++++++++++++++++++

        There Are No Menu Resources in This Application

+++++++++++++++++ DIALOG INFORMATION ++++++++++++++++++

        There Are No Dialog Resources in This Application

+++++++++++++++++++ IMPORTED FUNCTIONS ++++++++++++++++++
Number of Imported Modules =    1 (decimal)

   Import Module 001: USER32.dll

+++++++++++++++++++ IMPORT MODULE DETAILS +++++++++++++++

   Import Module 001: USER32.dll

 Addr:00002038 hint(01BB) Name: MessageBoxA

+++++++++++++++++++ EXPORTED FUNCTIONS ++++++++++++++++++
Number of Exported Functions = 0000 (decimal)




+++++++++++++++++++ ASSEMBLY CODE LISTING ++++++++++++++++++
//********************** Start of Code in Object .text **************
Program Entry Point = 00401000 (C:\Developments\MASM32\Projects\New Folder\main.exe File Offset:00001600)



//******************** Program Entry Point ********
:00401000 6A00		push 00000000
:00401002 680D304000	push 0040300D

* Possible StringData Ref from Data Obj ->"Hello World!"
                                  |
:00401007 6800304000	push 00403000
:0040100C 6A00		push 00000000

* Reference To: USER32.MessageBoxA, Ord:01BBh
                                  |
:0040100E E801000000	Call 00401014
:00401013 C3		ret



* Reference To: USER32.MessageBoxA, Ord:01BBh
                                  |
:00401014 FF2500204000            Jmp dword ptr [00402000]
:0040101A 00000000000000000000    BYTE 10 DUP(0)
:00401024 00000000000000000000    BYTE 10 DUP(0)
:0040102E 00000000000000000000    BYTE 10 DUP(0)
:00401038 00000000000000000000    BYTE 10 DUP(0)
:00401042 00000000000000000000    BYTE 10 DUP(0)
:0040104C 00000000000000000000    BYTE 10 DUP(0)
:00401056 00000000000000000000    BYTE 10 DUP(0)
:00401060 00000000000000000000    BYTE 10 DUP(0)
:0040106A 00000000000000000000    BYTE 10 DUP(0)
:00401074 00000000000000000000    BYTE 10 DUP(0)
:0040107E 00000000000000000000    BYTE 10 DUP(0)
:00401088 00000000000000000000    BYTE 10 DUP(0)
:00401092 00000000000000000000    BYTE 10 DUP(0)
:0040109C 00000000000000000000    BYTE 10 DUP(0)
:004010A6 00000000000000000000    BYTE 10 DUP(0)
:004010B0 00000000000000000000    BYTE 10 DUP(0)
:004010BA 00000000000000000000    BYTE 10 DUP(0)
:004010C4 00000000000000000000    BYTE 10 DUP(0)
:004010CE 00000000000000000000    BYTE 10 DUP(0)
:004010D8 00000000000000000000    BYTE 10 DUP(0)
:004010E2 00000000000000000000    BYTE 10 DUP(0)
:004010EC 00000000000000000000    BYTE 10 DUP(0)
:004010F6 00000000000000000000    BYTE 10 DUP(0)
:00401100 00000000000000000000    BYTE 10 DUP(0)
:0040110A 00000000000000000000    BYTE 10 DUP(0)
:00401114 00000000000000000000    BYTE 10 DUP(0)
:0040111E 00000000000000000000    BYTE 10 DUP(0)
:00401128 00000000000000000000    BYTE 10 DUP(0)
:00401132 00000000000000000000    BYTE 10 DUP(0)
:0040113C 00000000000000000000    BYTE 10 DUP(0)
:00401146 00000000000000000000    BYTE 10 DUP(0)
:00401150 00000000000000000000    BYTE 10 DUP(0)
:0040115A 00000000000000000000    BYTE 10 DUP(0)
:00401164 00000000000000000000    BYTE 10 DUP(0)
:0040116E 00000000000000000000    BYTE 10 DUP(0)
:00401178 00000000000000000000    BYTE 10 DUP(0)
:00401182 00000000000000000000    BYTE 10 DUP(0)
:0040118C 00000000000000000000    BYTE 10 DUP(0)
:00401196 00000000000000000000    BYTE 10 DUP(0)
:004011A0 00000000000000000000    BYTE 10 DUP(0)
:004011AA 00000000000000000000    BYTE 10 DUP(0)
:004011B4 00000000000000000000    BYTE 10 DUP(0)
:004011BE 00000000000000000000    BYTE 10 DUP(0)
:004011C8 00000000000000000000    BYTE 10 DUP(0)
:004011D2 00000000000000000000    BYTE 10 DUP(0)
:004011DC 00000000000000000000    BYTE 10 DUP(0)
:004011E6 00000000000000000000    BYTE 10 DUP(0)
:004011F0 00000000000000000000    BYTE 10 DUP(0)
:004011FA 00000000000038200000    BYTE 10 DUP(0)
 
 
 
 
 
 
:FFFFFFFF    End Of Listing

Seperti yang anda lihat, W32DASM mengeluarkan output seperti di atas kerana ia tahu yang program main.exe kita adalah dalam format PE. Jika W32DASM tidak mengenali format ini maka sudah tentu ia akan mengeluarkan kod disassembly bermula daripada offset 0 program kita iaitu bermula pada 'MZ' signature. Jika anda lihat output di atas, W32DASM bukan sahaja mengeluarkan output disassembly, tetapi juga menganalisa program ini seperti menunjukkan saiz kod dan data sections. Menunjukkan samada terdapat menu dan dialog resource dan sebagainya. Ia memulakan disassembly listing bermula pada program entry point (PEP) WIn32 program. Untuk mengetahui apakah maksud2 output di atas atau memudahkan anda menggunakan disassembler dengan berkesan, anda haruslah tahu keupayaan disassembler yang anda gunakansamada ia mengenali format file yang anda hendak disassemble. Seperti yang anda lihat pad akod saya, ia mengimport satu function daripada user32.dll iaitu MessageBoxA dan ini dapat dikenalpasti oleh W32DASM dengan menganalisa import table dalam seksyen tertentu dalam program kita. Ia akan dapat mengetahui function dan library yang kita gunakan dengan menganalisa bahagian ini mengikut seperti yang didokumenkan oleh Microsoft untuk format PE. Kadangkala disassembler tidak mampu untuk mengeluarkan output yang betul kerana program tersebut telah di'pack' atau di'encrypt'kan dan dengan itu ia tidak dapat menganalisa seksyen di dalam program dengan betul. Program tersebut dapat dilaksanakan kerana terdapat 'loader' di dalam program tersebut yang akan mengembalikan struktur asal program tersebut semasa runtime. Anda akan dapat melihatnya dengan menggunakan debugger. Anda sepatutnya tahu mengenai format PE atau apa sahaj format fail yang anda hendak reverse engineer supaya anda tahu apa yang anda boleh lakukan.

Kod disassembly untuk memaparkan message box :

:00401000 6A00		push 00000000
:00401002 680D304000	push 0040300D

* Possible StringData Ref from Data Obj ->"Hello World!"
                                  |
:00401007 6800304000	push 00403000
:0040100C 6A00		push 00000000

* Reference To: USER32.MessageBoxA, Ord:01BBh
                                  |
:0040100E E801000000	Call 00401014
:00401013 C3		ret

Daripada listing di atas kita tahu bahawa 403000 adalah lokasi untuk string "Hello World!" manakala 40300D adalah lokasi untuk string "Test". Jika anda perhatikan, call kepada messagebox still berada dalam program kita instead of terus ke user32.dll. Sebenarnya apa yang berlaku ialah, linker menyediakan satu jump table yang akan jump ke fungsi dalam dll yang berkenaan. table ini akan diisi oleh Windows executable loader semasa program tersebut dilaksanakan. Oleh itu, program tidak perlu risau semasa compilation. Anda akan memahami semua ini dengan mudah jika anda memahami format PE. Anda juga akan tahu mengapa terdapat banyak 0 bytes selepas kod kita dah berakhir selepas membaca tentangnya :). Saya akan membincangkan lebih lanjut mengenai penggunaan disassembler di masa akan datang dan juga mengenai disassembler lain seperti HIEW dan IDA yang selalu saya gunakan.

}

Kembali ke Isi Kandungan