hello.asm



In naturally computer just know 0 and 1 (binnary), it will processing an instruction which created only from 0 and 1, and this stat usually call as a machine language. Assembly is a low level language and almost like as a machine language.

In machine language, if we want to save a value of an EAX register to the stack we must creating an instruction "01010000", but in Assembly we just create an instruction "PUSH EAX", that's just some differences about an assembly and machine language.

Why must we learn about an assembly language?
Because it is the most important if we want to Reverse Engineering an aplication and it was use full if we want to create our own shellcode in exploit development.

There are two ways to create a syntax in assembly, that are AT&T and NASM. AT&T syntax usually used in GNU like a GNU Assembler, and become as a default syntax in GNU Debugger (GDB), and the NASM syntax usually used a lot in windows area.
Some differeces way of create the syntax are :

  • NASM is begining the comment with ";",  and AT&T is begin with #(hash)
  • In AT&T every register always beginning with "%", and not in NASM.
  • In AT&T every variable constant always beginning with "$", and not in NASM.
  • In the syntax with using operand source and destination, the AT&T have a command as  "cmd <source>,<dest>", and the NASM way is "cmd <dest>,<source>".
For example if we want insert a value 0x41424344 in EBX :
In NASM way        : MOV EBX,0x41424344 ; insert a value DCBA in register EBX
and in AT&T way   : MOVL $0x41424344,%EBX # insert a value DCBA in register EBX

Let's knowing some registers which used in intel processor.
Some general purpose registers are :
AX     Acumulator Register, usually used as a contains the return value of a function call.
CX     Count Register, usually used as a loop counter, "this" pointer in C++.
BX     Base Register , is a general purpose
DX     Data Register , is a general purpose
SI      Source index pointer, used as offset source in an operation which using a block memory
DI      Destination index pointer, used as offset dest in an operation which using a block memory
SP     Stack Pointer, is a upper of the stack
BP     Stack Base Pointer, is a bottom of the stack

That are some 16-bit general purpose and all of they have a 32-bit general purpose (extend), so they are become EAX,ECX,EBX,EDX,ESI,EDI,ESP,EBP in 32-bit general purpose.
For AX,CX,BX, and DX, they devided become 8-bit low register and 8-bit height register. In AX the 8-bit low register was calling AL and the 8-bit height was AH.

After we've knew some registers which used in an assembly, now we must knowing some instructions too.
Some instructions which used and created in a NASM way are :
ADD <dest>,<source> : Adds <source> to <dest>
SUB <dest>,<source> : Subtract <source> from <dest>
MUL <source> : Multiply the EDX:EAX registers (64-bit combo) by <source>
DIV <divisor> : Divide the EDX:EAX registers (64-bit combo) by <divisor>
INC <dest> : Add 1 to <dest>
DEC <dest> : Subtract 1 from <dest>
MOV <dest>, <source> : Move data from <source> to <dest>
CMP <dest>,<source> : Compare <source> with <dest>. Similar to sub instruction but doesn't modify the <dest> operand with the result of the subtraction
CALL <loc> : Call a function and return to the next instruction when finished
POP <dest> : Take a 32-bit value from the stack and store it in <dest>. ESP is incremented by 4
PUSH <value> : Adds a 32-bit value to the top of the stack. ESP is decremented by 4
JMP <loc> : Jump to <loc>
JE <loc> : Jump if Equal to <loc>
JG <loc> : Jump if Greater to <loc>
JGE <loc> : Jump if Greeater or Equal to <loc>
JLE <loc> : Jump if Less or Equal to <loc>
JNE <loc> : Jump if Not Equal to <loc>
JNZ <loc> : Jump if Not Zero to <loc>
JZ <loc> : Jump if Zero to <loc>
LEA <dest>, <source> : Load Effective Address, gets a pointer to the memory expression <source> and stores it in <dest>
ROL <dest>, <count> : Bitwise Rotate Left the value in <dest> by <count> bits.
ROR <dest>, <count> : Bitwise Rotate Right the value in <dest> by <count> bits.
SHL <dest>, <count> : Bitwise Shift Left the value in <dest> by <count> bits.  Zero bits added to the least significant bits.
SHR <dest>, <count> : Bitwise Shift Left the value in <dest> by <count> bits.  Zero bits added to the least significant bits.
TEST <dest>, <source> : Performs a logical OR operation but does not modify the value in the <dest> operand.
XCHG <dest, <source> : Exchange the contents of <source> and <dest>.
XOR <dest>, <source> : Bitwise XOR the value in <source> with the value in <dest>, storing the result in <dest>

Ok, may be introduction about an assembly is enough, now let's trying say HELLO with an assembly.
To writing a string HELLO to monitor with assembly, we needed a system call. System call is a kernel mode gateway for the programs which needed the services which just the kernel could do that.
To find out how to use a specific system call in assembly, first have a look at the system call’s man page to get more information about its functionality, required arguments, and return values.
From the man pages on Linux
# man 2 write

we find that the write system call is implemented as follows:
ssize_t write(int fd, const void *buf, size_t count);

from the man page system call (write), we've saw if it needed 3 argument, that are : integer as a descriptor, a string location, and integer as the length of string.
If the argument saved in register from EBX, ECX, and EDX, the first argument in register EBX, the second in ECX, and the third in EDX, and EAX is saving the number of system call.
Some number of system call which used in linux's kernel are :
#define __NR_restart_syscall   0
#define __NR_exit   1
#define __NR_fork   2
#define __NR_read   3
#define __NR_write   4
#define __NR_open   5
#define __NR_close   6
#define __NR_waitpid   7
#define __NR_creat   8
for more information about a system call numbers let's visit here.

OK let's type the instruction assembly above, here i'm using NASM way

global _start
_start:
;system call write(int,string,lengthstring)
xor eax,eax ; make sure if register EAX is clean
push byte 0xa ; insert newline "\n" to the stack
push 0x21646C72 ; insert "rld!" to the stack
push 0x6F57206F ; insert "o Wo" to the stack
push 0x6C6C6548 ; insert "Hell" to the stack
mov bl,1 ; insert 1 in bl as a value of argument system call
mov ecx,esp ; insert string in the stack to ecx
mov edx,13 ; insert lenstring 13 as a argument system call
mov al,4 ; insert number of write system call
int 0x80 ; calling system call

Some describe of that script :
push 0x21646C72 : if the hex translated in ascii it will become "!dlr", why we've insert like that and why must 4-byte character? It's causes my processor will read the stack with little-endien so the string become "rld!" and remember that the stack will become LAST IN FIRST OUT (LIFO) so the formation of inserting to the stack become like that. And the instruction just can inserted 4-byte character/offset
mov bl,1 : Why must using bl, not ebx? Cause we just insert 1 byte integer so we just needed 8-bit of reg BX and we choose bl cause the reg will read from the lowest
int 0x80 : Here we're calling system call with hex 0x80

Now let's compile that with syntax :
# nasm -f elf hello.asm
# ld -s -o hello hello.o

Now let try to running it :
# ./hello

Yes, it was running. But there is a problem with "Segmentation fault"
May be we need a system call exit(), now see an exit man page and the implemented of exit system call is :
void exit(int status);

the exit system call just need 1 argument wich typed integer, and here we're using EBX register to insert that value, and our hello.asm become :

global _start
_start:
;system call write(int,string,lengthstring)
xor eax,eax ; make sure if register EAX is clean
push byte 0xa ; insert newline "\n" to the stack
push 0x21646C72 ; insert "rld!" to the stack
push 0x6F57206F ; insert "o Wo" to the stack
push 0x6C6C6548 ; insert "Hell" to the stack
mov bl,1 ; insert 1 in bl as a value of argument system call
mov ecx,esp ; insert string in the stack to ecx
mov edx,13 ; insert lenstring 13 as a argument system call
mov al,4 ; insert number of write system call
int 0x80 ; calling system call
;system call exit(int)
xor eax,eax ; cleaning the eax again
mov al,1 ; insert number of exit system call
int 0x80 ; calling system call

and now compile again
# nasm -f elf hello.asm
# ld -s -o hello hello.o

and running again, than the result is :

0 comments:

Post a Comment