Skip to main content

100 Reps

PicoCTF: The Debugger

GDB baby step 1 

Can you figure out what is in the eax register at the end of the main function? 
For Mac, gdb can be installed via homebrew: brew install gdbGDB baby step 2
Learn how to disassemble a program from binary file.

Here we can see that in line 15, 0x86342 is copied into eax.
The output here seems to reverse the arguments.

Static analysis is understanding the behaviour of a program by reading the code. Dynamic analysis is understanding the behaviour through running the program and "seeing what happens" Learn how to set a breakpoint

GDB baby step 2

Can you figure out what is in the eax register at the end of the main function? 

Static analysis
The code all the way up to line 36 sets up initial values.
The most important ones to note are in lines 15 and 29 which copies 0x1e0da into the rbp-0x4 address and 0x0 into the rbp-0x8 address
The code skips lines 38 to 44 by jumping down to line 48 where ut cioues rbp-0x8 to eax.
If the value of eax is less than rbp-0xc (0x25f) then jump to line 38
The value in eax will keep changing until the check on line 51 returns a greater than.
Then rbp-0x4 is copied into eax

Dynamic analysis
Set a breakpoint at line 59 to avoid calculating all that.

GDB baby step 3

Dump of assembler code for function main:
    0x0000000000401106 <+0>:	endbr64 
    0x000000000040110a <+4>:	push   %rbp
    0x000000000040110b <+5>:	mov    %rsp,%rbp
    0x000000000040110e <+8>:	mov    %edi,-0x14(%rbp)
    0x0000000000401111 <+11>:	mov    %rsi,-0x20(%rbp)
    0x0000000000401115 <+15>:	movl   $0x2262c96b,-0x4(%rbp)
    0x000000000040111c <+22>:	mov    -0x4(%rbp),%eax
    0x000000000040111f <+25>:	pop    %rbp
    0x0000000000401120 <+26>:	ret    
 End of assembler dump.
I set the break point at line 22

    (gdb) break *main+22
    Breakpoint 1 at 0x40111c    
Then run the program. It should stop at the breakpoint
    (gdb) run    
    [Thread debugging using libthread_db enabled]
    Breakpoint 1, 0x000000000040111c in main ()
Use the "x" command to read the memory address rbp-0x4. The syntax reads like this: Use x with these parameters 4xb - 4 bytes in hex format (x)
    (gdb) x/4xb $rbp-0x4
    0x7fffffffd7ec:	0x6b	0xc9	0x62	0x22   
GDB baby step 4 Disassembling main gives you this:

(gdb) disassemble main
Dump of assembler code for function main:
   0x000000000040111c <+0>:	endbr64 
   0x0000000000401120 <+4>:	push   %rbp
   0x0000000000401121 <+5>:	mov    %rsp,%rbp
   0x0000000000401124 <+8>:	sub    $0x20,%rsp
   0x0000000000401128 <+12>:	mov    %edi,-0x14(%rbp)
   0x000000000040112b <+15>:	mov    %rsi,-0x20(%rbp)
   0x000000000040112f <+19>:	movl   $0x28e,-0x4(%rbp)
   0x0000000000401136 <+26>:	movl   $0x0,-0x8(%rbp)
   0x000000000040113d <+33>:	mov    -0x4(%rbp),%eax
   0x0000000000401140 <+36>:	mov    %eax,%edi
   0x0000000000401142 <+38>:	call   0x401106 <func1>
   0x0000000000401147 <+43>:	mov    %eax,-0x8(%rbp)
   0x000000000040114a <+46>:	mov    -0x4(%rbp),%eax
   0x000000000040114d <+49>:	leave  
   0x000000000040114e <+50>:	ret    
End of assembler dump.

Disassembling func1 gets you this

(gdb) disassemble func1
Dump of assembler code for function func1:
   0x0000000000401106 <+0>:	endbr64 
   0x000000000040110a <+4>:	push   %rbp
   0x000000000040110b <+5>:	mov    %rsp,%rbp
   0x000000000040110e <+8>:	mov    %edi,-0x4(%rbp)
   0x0000000000401111 <+11>:	mov    -0x4(%rbp),%eax
   0x0000000000401114 <+14>:	imul   $0x3269,%eax,%eax
   0x000000000040111a <+20>:	pop    %rbp
   0x000000000040111b <+21>:	ret    
End of assembler dump.

We can see the constant being multiplied is 0x3269


(gdb) disassemble main
Dump of assembler code for function main:
   0x0000000000001169 <+0>:	endbr64 
   0x000000000000116d <+4>:	push   %rbp
   0x000000000000116e <+5>:	mov    %rsp,%rbp
   0x0000000000001171 <+8>:	sub    $0x30,%rsp
   0x0000000000001175 <+12>:	mov    %fs:0x28,%rax
   0x000000000000117e <+21>:	mov    %rax,-0x8(%rbp)
   0x0000000000001182 <+25>:	xor    %eax,%eax
   0x0000000000001184 <+27>:	movb   $0x70,-0x30(%rbp)
   0x0000000000001188 <+31>:	movb   $0x69,-0x2f(%rbp)
   0x000000000000118c <+35>:	movb   $0x63,-0x2e(%rbp)
   0x0000000000001190 <+39>:	movb   $0x6f,-0x2d(%rbp)
   0x0000000000001194 <+43>:	movb   $0x43,-0x2c(%rbp)
   0x0000000000001198 <+47>:	movb   $0x54,-0x2b(%rbp)
   0x000000000000119c <+51>:	movb   $0x46,-0x2a(%rbp)
   0x00000000000011a0 <+55>:	movb   $0x7b,-0x29(%rbp)
   0x00000000000011a4 <+59>:	movb   $0x41,-0x28(%rbp)
   0x00000000000011a8 <+63>:	movb   $0x53,-0x27(%rbp)
   0x00000000000011ac <+67>:	movb   $0x43,-0x26(%rbp)
   0x00000000000011b0 <+71>:	movb   $0x49,-0x25(%rbp)
   0x00000000000011b4 <+75>:	movb   $0x49,-0x24(%rbp)
   0x00000000000011b8 <+79>:	movb   $0x5f,-0x23(%rbp)
   0x00000000000011bc <+83>:	movb   $0x49,-0x22(%rbp)
   0x00000000000011c0 <+87>:	movb   $0x53,-0x21(%rbp)
   0x00000000000011c4 <+91>:	movb   $0x5f,-0x20(%rbp)
   0x00000000000011c8 <+95>:	movb   $0x45,-0x1f(%rbp)
   0x00000000000011cc <+99>:	movb   $0x41,-0x1e(%rbp)
   0x00000000000011d0 <+103>:	movb   $0x53,-0x1d(%rbp)
   0x00000000000011d4 <+107>:	movb   $0x59,-0x1c(%rbp)
   0x00000000000011d8 <+111>:	movb   $0x5f,-0x1b(%rbp)
   0x00000000000011dc <+115>:	movb   $0x33,-0x1a(%rbp)
   0x00000000000011e0 <+119>:	movb   $0x43,-0x19(%rbp)
   0x00000000000011e4 <+123>:	movb   $0x46,-0x18(%rbp)
   0x00000000000011e8 <+127>:	movb   $0x34,-0x17(%rbp)
   0x00000000000011ec <+131>:	movb   $0x42,-0x16(%rbp)
   0x00000000000011f0 <+135>:	movb   $0x46,-0x15(%rbp)
   0x00000000000011f4 <+139>:	movb   $0x41,-0x14(%rbp)
   0x00000000000011f8 <+143>:	movb   $0x44,-0x13(%rbp)
   0x00000000000011fc <+147>:	movb   $0x7d,-0x12(%rbp)
   0x0000000000001200 <+151>:	movzbl -0x30(%rbp),%eax
   0x0000000000001204 <+155>:	movsbl %al,%eax
   0x0000000000001207 <+158>:	mov    %eax,%esi
   0x0000000000001209 <+160>:	lea    0xdf4(%rip),%rdi        # 0x2004
   0x0000000000001210 <+167>:	mov    $0x0,%eax
   0x0000000000001215 <+172>:	call   0x1070 <printf@plt>
   0x000000000000121a <+177>:	nop
   0x000000000000121b <+178>:	mov    -0x8(%rbp),%rax
   0x000000000000121f <+182>:	xor    %fs:0x28,%rax
   0x0000000000001228 <+191>:	je     0x122f <main+198>
   0x000000000000122a <+193>:	call   0x1060 <__stack_chk_fail@plt>
   0x000000000000122f <+198>:	leave  
   0x0000000000001230 <+199>:	ret    
End of assembler dump.

Use the x command again to print out the string
x/s $rbp-0x30


Popular posts from this blog

PicoCTF: Low Level Binary Intro Playlist

Mochi's Tale Mochi's Tale is a really cool little game that teaches you how to "find things out" through experimentation. I found it a really helpful way to get you into the rhythm of learning rules without being told what they are in the first place.

Linux Admin: Managing Users

I read through Chapter 2 of Linux Admin for Absolute Beginners by Martin Stevenson Key Learnings: Add Users Passwords User groups How to add users The flags of adduser varies across different version of Linux, so consult the man pages for more info. I am practising on Kali Linux, the simplest command is: sudo adduser --comment "Gym Owner Terry Crews" tcrews You will need root access for this. So using the root user or adding sudo will work. Sometimes you'll see another command useradd instead. The recommendation is to always use adduser. adduser is a wrapper for useradd.  adduser is more user friendly and interactive than its back-end useradd . There's no difference in features provided. Why is this important? This is how we can create an account for users to access Linux servers. If you have a new employee at your company or student who enters the university, they'll need access to the shared drive, a private drive for themselves etc. Groups Groups keep users i