<< 5. Praktikum | NASM Lehele | 7. Praktikum >>

NASM – Praktikum6: Debugimine, Float, Libprax 2: memcmp

Selles praktikumis õpime debugimist Windows keskkonnas, vaatame põgusalt float arvutüüpe ning põhiliselt keskendume Libprax-i edasiarendusele.

Alusfailid:
Prax6.zip (Windows/Linux) 64-bit Linux vajab lisaks GCC 32/64-bit teeke: sudo apt-get install gcc-multilib

:/NASM/Prax6/
  `- Makefile
  `- libprax.h
  `- test.c
  ./libprax/
    `- io.asm
    `- lib.asm
    `- string.asm
    `- macros.inc

Vajalikud tööriistad

Windows: Visual Studio - Visual Studio 2015
Windows: x64dbg - x64dbg latest snapshot
Windows: OllyDbg - OllyDbg v2.01
Linux: Qt Creator - Ubuntu Software Center-ist või Qt Creator Downloads

1. Assemblerprogrammide Debugimine

Üldiselt võib assembler debugimine olla väga raske; eriti kui kirjutatud kood on liiga keeruline või lihtsalt ei tööta ilma igasuguse vihjeta mis võiks valesti olla. Debugimise võib kokku võtta järgmise tsitaadiga:

``Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.´´

— Brian W. Kernighan

Kui Inteli insenerid disainisid x86 arhitektuuri, lisasid nad spetsiifilise opkoodi, mis on mõeldud debugimise lihtsustamiseks. Käsk int XX käivitab masinas kindla katkestuse. Katkestus int 3 on aga eriline 1-baidine opkood, mis katkestab programmi töö ning annab juhtimise üle süsteemi Debuggerile, või ükskõik millise debuggeri, mis on hetkel programmi külge ühendatud.

int 3 ; trap to debugger

Väike näide int 3 kasutamisest:

section .text
global _main
_main:

	int 3				; break to debugger
	mov	eax, [ebx + 4]	; offending code

	xor eax, eax
	ret

Antud käsk int 3 on kasulik kiirelt programmi debugimiseks, sest saame hõlpsasti valida koodirea kus Debugger peatub ilma Debuggerit ennast seadistamata. Murdepunkti seadmine võib mõnel juhul (gdb) olla vägagi tülikas.

Järgnevalt jaguneb Debugimise teema kaheks; vali endale sobiv:



Siinkohal lõpetaks debugimise teema. Rohkem lugemiste murdepunktidega debugimisest leiab järgmises suurepärases artiklis Anti-Reverse Engineering: http://www.codeproject.com/KB/security/AntiReverseEngineering.aspx.
Lisaks võib uurida Interactive Disassembler - IDA 5.0 Freeware programmi, mis on mõeldud binaarsete programmide lahtimurdmiseks ja debugimiseks.


2. Floating Point - FPU käsud

Kahjuks jääb Float arvudega detailsem kokkupuude kursuse raamidest välja ning vajab palju rohkem tähelepanu kui tavalised X86 aritmeetikakäsud. Hea resurss FPU käskude õppimiseks leiab järgnevalt lingilt: X86 FPU Tutorial.

Üldised FPU käsud:

FLD src - Load float to float stack
	fld		0.15			; load immediate:			0.15 --> fpush st(0)
	fld		qword[dvalue]	; load double: 				qword[dvalue] --> fpush st(0)
	fld		st(3)			; load from float stack[3]: st(3) --> fpush st(0)
FST dst - Store float from top of the stack to dst
	fst		st(3)			; st(0) --> st(3)
	fst		dword[eax]		; st(0) --> dword[eax]
FSTP dst - Store real number and Pop the top data register
	fstp	qword[edx]		; fpop st(0) --> qword[edx]
	fstp	st(4)			; fpop st(0) --> st(4)
FLDZ, FLD1, FLDPI - Load value: Zero, One, PI
	fldz	; 0.00 --> st(0)
	fld1	; 1.00 --> st(0)
	fldpi	; 3.14... --> st(0)
FILD src - Integer load from memory
	fild	dword[ebp-4]	; int --> float st(0)
	fild	int_var			; int_var --> float st(0)
FIST dst - Integer store integer to memory
	fist	dword[ebp-4]	; float st(0) --> int
	fist	int_vat			; float st(0) --> int_var
FISTP dst - Integer store integer to memory and pop the top of the float stack
	fistp	int_var			; float st(0) --> int;	fpop top

3. LIBPRAX Arendus

Eelmises praktikumis kirjutasime sõnefunktsioone, aitoa funktsiooni ning iseseisvalt jäi lahendada aftoa. Selles praktikumis kirjutaks juurde memcmp ja lõpetaks aputi ning aputf.

Funktsioon amemcmp võrdleb kahte fikseeritud suurusega mälublokki. Kui mälublokid on võrdsed, siis on tulem 0. Kui mälubloki A bait kohal [i] on väiksem kui mälubloki B bait kohal [i], siis on tulem -1. Ülejäänud juhtudel on tulem 1.

int __cdecl amemcmp(const void* A, const void* B, int len)
{
	while(len)
	{
		if (*A < *B)
			return -1;
		else if(*A > *B)
			return 1;
		++A;
		++B;
		--len;
	}
	return 0;
}

Funktsioon aputi kutsub välja aitoa + aprints funktsioonid.

int __cdecl aputi(int i)
{
	char buffer[24];
	aitoa(buffer, i);
	return aprints(buffer);
}

Funktsioon aputf on analoogne aitoa funktsiooniga, aga vajab natuke suuremat puhvrit.


4. Kokkuvõte

Selles praktikumis keskendusime just Debugimisele, vaadates läbi erinevaid variante Debuggerite ja IDE-de lahendustest. Muidugi pole nimekiri lõplik ning Windows/Linux platvormidele on veel tosinaid analoogseid debuggereid saadaval.

Praktikumi lahendus:
Prax6-complete.zip (Windows/Linux)

<< 5. Praktikum | NASM Lehele | 7. Praktikum >>