Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
Another week, and another post about my SLAE progress! This time, I’ll be covering assembly saving flags and registers.
While the opcodes to save flags and registers are fairly simple, this is the third program (after “Hello World” and multiplication/division) that I wrote on my own for SLAE.
I’m sure you all are getting tired of my code posts that aren’t really tutorials, but I’m getting closer to being ready for the SLAE exam at least!
For this exercise, I had to write a program that performed the following actions.
The code is pretty similar to my “Hello World” application, so I will only cover the differences.
First, I have added a hello world procedure that will actually do the printing of my “message” to the screen. This code is exactly the same as my previous application, with two additions. These additions are a function prologue (enter 0, 0) and epilogue (leave; ret).
The function prologue functions similarly to a (push ebp; mov ebp, esp; sub esp 0). This performs the first half of the second requirement, which is saving the frame pointer. The function epilogue is functionally similar to (mov esp, ebp; pop ebp; ret). Similarly to the function prologue, this restores the same frame pointer from the beginning of the procedure.
With the second requirement covered, let’s move on to the _start label. In this case, it only contains a (mov ecx, 0x5). This will be a counter for the number of times we will loop. In this case, the program will print “Hello World!” 5 times, and this also serves as an example for saving a register (requirement #1).
The PrintHelloWorld section is a bit different as well. First up, we have the pushad and pushfd instructions. These fulfill the first half of the first requirement, which is saving the registers and flags before calling the procedure. Pushad/pushfd push the contents of the general purpose registers and flags (respectively) onto the stack, and adjust the stack pointer accordingly. After the call to HelloWorldProc, the program will execute the popad and popfd instructions, which reset the registers and flags to their original values.
With both requirements met, the procedure loops, and then cleanly exits.
The full code for this example is found below.
; Filename: HelloWorldSaveState.nasm ; Author: Ray Doyle ; Reference: https://en.wikipedia.org/wiki/Function_prologue global _start section .text HelloWorldProc: enter 0, 0 ; Print hello world using write syscall mov eax, 0x4 mov ebx, 0x1 mov ecx, message mov edx, mlen int 0x80 leave ret _start: mov ecx, 0x5 PrintHelloWorld: ; preserve registers and flags pushad pushfd call HelloWorldProc ; restore registers and stack popfd popad loop PrintHelloWorld mov eax, 1 mov ebx, 10 ; sys_exit syscall int 0x80 section .data message: db "Hello World!" mlen equ $-message
Before tracing the execution, it is important to test that the program actually works. As expected, the program prints “Hello World!” five times before exiting.
doyler@slae:~/slae/module1-10$ vi HelloWorldSaveState.nasm doyler@slae:~/slae/module1-10$ sh ../compile.sh HelloWorldSaveState [+] Assembling with Nasm ... [+] Linking ... [+] Done! doyler@slae:~/slae/module1-10$ ls HelloWorldSaveState HelloWorldSaveState.nasm HelloWorldSaveState.o doyler@slae:~/slae/module1-10$ ./HelloWorldSaveState Hello World!Hello World!Hello World!Hello World!Hello World!
With the program verified as working, it was time for me to trace the execution. I’ve cut out most of the loop, but the general program flow still holds true:
doyler@slae:~/slae/module1-10$ gdb -q HelloWorldSaveState Reading symbols from /home/doyler/slae/module1-10/HelloWorldSaveState...(no debugging symbols found)...done. (gdb) set disassembly-flavor intel (gdb) break _start Breakpoint 1 at 0x804809c (gdb) define hook-stop Type commands for definition of "hook-stop". End with a line saying just "end". >print/x $eax >print/x $ebx >print/x $ecx >print/x $edx >print/x $ebp >x/xw &message >x/4xw $esp >disassemble $eip,+10 >end (gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/doyler/slae/module1-10/HelloWorldSaveState $22 = 0x0 $23 = 0x0 $24 = 0x0 $25 = 0x0 $26 = 0x0 0x80490b8 <message>: 0x6c6c6548 0xbffff3d0: 0x00000001 0xbffff53a 0x00000000 0xbffff56b Dump of assembler code from 0x804809c to 0x80480a6: => 0x0804809c <_start+0>: mov ecx,0x5 0x080480a1 <PrintHelloWorld+0>: pusha 0x080480a2 <PrintHelloWorld+1>: pushf 0x080480a3 <PrintHelloWorld+2>: call 0x8048080 <HelloWorldProc> End of assembler dump. Breakpoint 1, 0x0804809c in _start () (gdb) nexti $27 = 0x0 $28 = 0x0 $29 = 0x5 $30 = 0x0 $31 = 0x0 0x80490b8 <message>: 0x6c6c6548 0xbffff3d0: 0x00000001 0xbffff53a 0x00000000 0xbffff56b Dump of assembler code from 0x80480a1 to 0x80480ab: => 0x080480a1 <PrintHelloWorld+0>: pusha 0x080480a2 <PrintHelloWorld+1>: pushf 0x080480a3 <PrintHelloWorld+2>: call 0x8048080 <HelloWorldProc> 0x080480a8 <PrintHelloWorld+7>: popf 0x080480a9 <PrintHelloWorld+8>: popa 0x080480aa <PrintHelloWorld+9>: loop 0x80480a1 <PrintHelloWorld> End of assembler dump. 0x080480a1 in PrintHelloWorld () (gdb) nexti $32 = 0x0 $33 = 0x0 $34 = 0x5 $35 = 0x0 $36 = 0x0 0x80490b8 <message>: 0x6c6c6548 0xbffff3b0: 0x00000000 0x00000000 0x00000000 0xbffff3d0 Dump of assembler code from 0x80480a2 to 0x80480ac: => 0x080480a2 <PrintHelloWorld+1>: pushf 0x080480a3 <PrintHelloWorld+2>: call 0x8048080 <HelloWorldProc> 0x080480a8 <PrintHelloWorld+7>: popf 0x080480a9 <PrintHelloWorld+8>: popa 0x080480aa <PrintHelloWorld+9>: loop 0x80480a1 <PrintHelloWorld> End of assembler dump. 0x080480a2 in PrintHelloWorld () (gdb) print $eflags $37 = [ IF ] (gdb) nexti $38 = 0x0 $39 = 0x0 $40 = 0x5 $41 = 0x0 $42 = 0x0 0x80490b8 <message>: 0x6c6c6548 0xbffff3ac: 0x00000302 0x00000000 0x00000000 0x00000000 Dump of assembler code from 0x80480a3 to 0x80480ad: => 0x080480a3 <PrintHelloWorld+2>: call 0x8048080 <HelloWorldProc> 0x080480a8 <PrintHelloWorld+7>: popf 0x080480a9 <PrintHelloWorld+8>: popa 0x080480aa <PrintHelloWorld+9>: loop 0x80480a1 <PrintHelloWorld> 0x080480ac <PrintHelloWorld+11>: mov eax,0x1 End of assembler dump. 0x080480a3 in PrintHelloWorld () (gdb) nexti $43 = 0x0 $44 = 0x0 $45 = 0x5 $46 = 0x0 $47 = 0x0 0x80490b8 <message>: 0x6c6c6548 0xbffff3a8: 0x080480a8 0x00000302 0x00000000 0x00000000 Dump of assembler code from 0x8048080 to 0x804808a: => 0x08048080 <HelloWorldProc+0>: enter 0x0,0x0 0x08048084 <HelloWorldProc+4>: mov eax,0x4 0x08048089 <HelloWorldProc+9>: mov ebx,0x1 End of assembler dump. 0x08048080 in HelloWorldProc () (gdb) nexti $48 = 0x0 $49 = 0x0 $50 = 0x5 $51 = 0x0 $52 = 0xbffff3a4 0x80490b8 <message>: 0x6c6c6548 0xbffff3a4: 0x00000000 0x080480a8 0x00000302 0x00000000 Dump of assembler code from 0x8048084 to 0x804808e: => 0x08048084 <HelloWorldProc+4>: mov eax,0x4 0x08048089 <HelloWorldProc+9>: mov ebx,0x1 End of assembler dump. 0x08048084 in HelloWorldProc () (gdb) nexti $53 = 0x4 $54 = 0x0 $55 = 0x5 $56 = 0x0 $57 = 0xbffff3a4 0x80490b8 <message>: 0x6c6c6548 0xbffff3a4: 0x00000000 0x080480a8 0x00000302 0x00000000 Dump of assembler code from 0x8048089 to 0x8048093: => 0x08048089 <HelloWorldProc+9>: mov ebx,0x1 0x0804808e <HelloWorldProc+14>: mov ecx,0x80490b8 End of assembler dump. 0x08048089 in HelloWorldProc () (gdb) nexti $58 = 0x4 $59 = 0x1 $60 = 0x5 $61 = 0x0 $62 = 0xbffff3a4 0x80490b8 <message>: 0x6c6c6548 0xbffff3a4: 0x00000000 0x080480a8 0x00000302 0x00000000 Dump of assembler code from 0x804808e to 0x8048098: => 0x0804808e <HelloWorldProc+14>: mov ecx,0x80490b8 0x08048093 <HelloWorldProc+19>: mov edx,0xc End of assembler dump. 0x0804808e in HelloWorldProc () (gdb) nexti $63 = 0x4 $64 = 0x1 $65 = 0x80490b8 $66 = 0x0 $67 = 0xbffff3a4 0x80490b8 <message>: 0x6c6c6548 0xbffff3a4: 0x00000000 0x080480a8 0x00000302 0x00000000 Dump of assembler code from 0x8048093 to 0x804809d: => 0x08048093 <HelloWorldProc+19>: mov edx,0xc 0x08048098 <HelloWorldProc+24>: int 0x80 0x0804809a <HelloWorldProc+26>: leave 0x0804809b <HelloWorldProc+27>: ret 0x0804809c <_start+0>: mov ecx,0x5 End of assembler dump. 0x08048093 in HelloWorldProc () (gdb) nexti $68 = 0x4 $69 = 0x1 $70 = 0x80490b8 $71 = 0xc $72 = 0xbffff3a4 0x80490b8 <message>: 0x6c6c6548 0xbffff3a4: 0x00000000 0x080480a8 0x00000302 0x00000000 Dump of assembler code from 0x8048098 to 0x80480a2: => 0x08048098 <HelloWorldProc+24>: int 0x80 0x0804809a <HelloWorldProc+26>: leave 0x0804809b <HelloWorldProc+27>: ret 0x0804809c <_start+0>: mov ecx,0x5 0x080480a1 <PrintHelloWorld+0>: pusha End of assembler dump. 0x08048098 in HelloWorldProc () (gdb) nexti Hello World!$73 = 0xc $74 = 0x1 $75 = 0x80490b8 $76 = 0xc $77 = 0xbffff3a4 0x80490b8 <message>: 0x6c6c6548 0xbffff3a4: 0x00000000 0x080480a8 0x00000302 0x00000000 Dump of assembler code from 0x804809a to 0x80480a4: => 0x0804809a <HelloWorldProc+26>: leave 0x0804809b <HelloWorldProc+27>: ret 0x0804809c <_start+0>: mov ecx,0x5 0x080480a1 <PrintHelloWorld+0>: pusha 0x080480a2 <PrintHelloWorld+1>: pushf 0x080480a3 <PrintHelloWorld+2>: call 0x8048080 <HelloWorldProc> End of assembler dump. 0x0804809a in HelloWorldProc () (gdb) nexti $78 = 0xc $79 = 0x1 $80 = 0x80490b8 $81 = 0xc $82 = 0x0 0x80490b8 <message>: 0x6c6c6548 0xbffff3a8: 0x080480a8 0x00000302 0x00000000 0x00000000 Dump of assembler code from 0x804809b to 0x80480a5: => 0x0804809b <HelloWorldProc+27>: ret 0x0804809c <_start+0>: mov ecx,0x5 0x080480a1 <PrintHelloWorld+0>: pusha 0x080480a2 <PrintHelloWorld+1>: pushf 0x080480a3 <PrintHelloWorld+2>: call 0x8048080 <HelloWorldProc> End of assembler dump. 0x0804809b in HelloWorldProc () (gdb) nexti $83 = 0xc $84 = 0x1 $85 = 0x80490b8 $86 = 0xc $87 = 0x0 0x80490b8 <message>: 0x6c6c6548 0xbffff3ac: 0x00000302 0x00000000 0x00000000 0x00000000 Dump of assembler code from 0x80480a8 to 0x80480b2: => 0x080480a8 <PrintHelloWorld+7>: popf 0x080480a9 <PrintHelloWorld+8>: popa 0x080480aa <PrintHelloWorld+9>: loop 0x80480a1 <PrintHelloWorld> 0x080480ac <PrintHelloWorld+11>: mov eax,0x1 0x080480b1 <PrintHelloWorld+16>: mov ebx,0xa End of assembler dump. 0x080480a8 in PrintHelloWorld () (gdb) nexti $88 = 0xc $89 = 0x1 $90 = 0x80490b8 $91 = 0xc $92 = 0x0 0x80490b8 <message>: 0x6c6c6548 0xbffff3b0: 0x00000000 0x00000000 0x00000000 0xbffff3d0 Dump of assembler code from 0x80480a9 to 0x80480b3: => 0x080480a9 <PrintHelloWorld+8>: popa 0x080480aa <PrintHelloWorld+9>: loop 0x80480a1 <PrintHelloWorld> 0x080480ac <PrintHelloWorld+11>: mov eax,0x1 0x080480b1 <PrintHelloWorld+16>: mov ebx,0xa End of assembler dump. 0x080480a9 in PrintHelloWorld () (gdb) print $eflags $93 = [ TF IF ] (gdb) nexti $94 = 0x0 $95 = 0x0 $96 = 0x5 $97 = 0x0 $98 = 0x0 0x80490b8 <message>: 0x6c6c6548 0xbffff3d0: 0x00000001 0xbffff53a 0x00000000 0xbffff56b Dump of assembler code from 0x80480aa to 0x80480b4: => 0x080480aa <PrintHelloWorld+9>: loop 0x80480a1 <PrintHelloWorld> 0x080480ac <PrintHelloWorld+11>: mov eax,0x1 0x080480b1 <PrintHelloWorld+16>: mov ebx,0xa End of assembler dump. 0x080480aa in PrintHelloWorld () ... (gdb) nexti $379 = 0x0 $380 = 0x0 $381 = 0x0 $382 = 0x0 $383 = 0x0 0x80490b8 <message>: 0x6c6c6548 0xbffff3d0: 0x00000001 0xbffff53a 0x00000000 0xbffff56b Dump of assembler code from 0x80480ac to 0x80480b6: => 0x080480ac <PrintHelloWorld+11>: mov eax,0x1 0x080480b1 <PrintHelloWorld+16>: mov ebx,0xa End of assembler dump. 0x080480ac in PrintHelloWorld () (gdb) nexti $384 = 0x1 $385 = 0x0 $386 = 0x0 $387 = 0x0 $388 = 0x0 0x80490b8 <message>: 0x6c6c6548 0xbffff3d0: 0x00000001 0xbffff53a 0x00000000 0xbffff56b Dump of assembler code from 0x80480b1 to 0x80480bb: => 0x080480b1 <PrintHelloWorld+16>: mov ebx,0xa 0x080480b6 <PrintHelloWorld+21>: int 0x80 0x080480b8: dec eax 0x080480b9: gs 0x080480ba: ins BYTE PTR es:[edi],dx End of assembler dump. 0x080480b1 in PrintHelloWorld () (gdb) nexti $389 = 0x1 $390 = 0xa $391 = 0x0 $392 = 0x0 $393 = 0x0 0x80490b8 <message>: 0x6c6c6548 0xbffff3d0: 0x00000001 0xbffff53a 0x00000000 0xbffff56b Dump of assembler code from 0x80480b6 to 0x80480c0: => 0x080480b6 <PrintHelloWorld+21>: int 0x80 0x080480b8: dec eax 0x080480b9: gs 0x080480ba: ins BYTE PTR es:[edi],dx 0x080480bb: ins BYTE PTR es:[edi],dx 0x080480bc: outs dx,DWORD PTR ds:[esi] 0x080480bd: and BYTE PTR [edi+0x6f],dl End of assembler dump. 0x080480b6 in PrintHelloWorld () (gdb) nexti [Inferior 1 (process 23862) exited with code 012] Error while running hook_stop: No registers.
While this was another fairly simple assembly program, it was one that I wrote on my own before the course demonstrated it to me.
The Intel instruction set manual is a great reference, and I see myself returning it to it plenty in the future.
There will be a large amount of assembly posts to come, but I will do my best to mix in some other topics here and there. If you do not like the formatting or style of these posts, then please let me know if you have any suggestions. I was hoping to include a bit of the GDB tracing to make it easier to follow, but it can definitely be a huge wall of text.
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he’s done it all. To show for it, he has obtained an OSCE, OSCP, eCPPT, GXPN, eWPT, eWPTX, SLAE, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!
He currently serves as a Senior Staff Adversarial Engineer for Avalara, and his previous position was a Principal Penetration Testing Consultant for Secureworks.
This page contains links to products that I may receive compensation from at no additional cost to you. View my Affiliate Disclosure page here. As an Amazon Associate, I earn from qualifying purchases.