Tags: misc 

Rating:

Welcome to the Beginner's Quest

Welcome to the Beginner's Quest. The Beginner's Quest is aimed for new CTF-goers who may not feel ready for the main event.

These writeups are done by Team IrisCS skat, also known as Shawn Duong. You can find my website at shawnduong.github.io and you can email me at shawnduong@pm.me.

I hope you enjoy reading these writeups as much as I enjoyed writing them!

Beginner's Quest

Invitation

Links: golden disc

Enter Space-Time Coordinates (misc)

Attachment

Alright, let's get started! It looks like we're given a zip file. Let's go ahead and unzip it and see what we're dealing with.

I first downloaded the challenge off of the website. Because it's a zip file, I use the unzip utility to extract the contents of the file into my current working directory. Then, I listed all of the files in my current working directory using ls, and then found out what types of files I'm dealing with by using the file utility and passing the * wildcard, which essentially means "everything," as in I want to find out the filetype of everything.

One of the files, rand2, is an ELF. ELF stands for Executable and Linkable Format, which basically means that it's an executable program file. In order to execute it, we need to set the appropriate mode, so we use the chmod utility (change mode) and pass +x (+executable) to specify that we want to make this file executable.

The other file, log.txt, is an ASCII text file. ASCII stands for the American Standard Code for Information Interchange, which basically means that it's readable text that we can understand as humans and not a bunch of binary machine jargon. We can read it using the cat utility.

Let's go ahead and run rand2 to see what it does.

It looks like it takes two inputs and then performs a comparison on them.

Method 1: Analysing Register Values and Ensuring Comparisons

During debugging, we can have a look at the value of registers involved in comparisons and directly set them to certain values in order to ensure that a comparison is done between two equal values.

Let's get started by debugging the program through gdb, the GNU Debugger.

We're going to set a breakpoint at main using break, so the program will halt execution when it reaches that function. Then, we're going to run the program using r. Once it reaches the breakpoint, it will halt execution. We're then going to perform a disassembly on the current stack frame to view the instructions underneath using disas.

Here's the full disassembly.

(gdb) disas
Dump of assembler code for function main:
=> 0x0000555555554872 <+0>:     push   rbp
   0x0000555555554873 <+1>:     mov    rbp,rsp
   0x0000555555554876 <+4>:     push   rbx
   0x0000555555554877 <+5>:     sub    rsp,0x38
   0x000055555555487b <+9>:     mov    DWORD PTR [rbp-0x34],edi
   0x000055555555487e <+12>:    mov    QWORD PTR [rbp-0x40],rsi
   0x0000555555554882 <+16>:    mov    edi,0x0
   0x0000555555554887 <+21>:    call   0x5555555546e0 <time@plt>
   0x000055555555488c <+26>:    mov    QWORD PTR [rip+0x200805],rax        # 0x555555755098 <seed>
   0x0000555555554893 <+33>:    lea    rdi,[rip+0x229]        # 0x555555554ac3
   0x000055555555489a <+40>:    call   0x5555555546b0 <puts@plt>
   0x000055555555489f <+45>:    mov    QWORD PTR [rbp-0x18],0x0
   0x00005555555548a7 <+53>:    jmp    0x555555554946 <main+212>
   0x00005555555548ac <+58>:    mov    rax,QWORD PTR [rbp-0x18]
   0x00005555555548b0 <+62>:    lea    rdx,[rax*8+0x0]
   0x00005555555548b8 <+70>:    lea    rax,[rip+0x2007a1]        # 0x555555755060 <destinations>
   0x00005555555548bf <+77>:    mov    rdx,QWORD PTR [rdx+rax*1]
   0x00005555555548c3 <+81>:    mov    rax,QWORD PTR [rbp-0x18]
   0x00005555555548c7 <+85>:    mov    rsi,rax
   0x00005555555548ca <+88>:    lea    rdi,[rip+0x205]        # 0x555555554ad6
   0x00005555555548d1 <+95>:    mov    eax,0x0
   0x00005555555548d6 <+100>:   call   0x5555555546c0 <printf@plt>
   0x00005555555548db <+105>:   mov    rax,QWORD PTR [rbp-0x18]
   0x00005555555548df <+109>:   lea    rdx,[rax*8+0x0]
   0x00005555555548e7 <+117>:   lea    rax,[rip+0x200772]        # 0x555555755060 <destinations>
   0x00005555555548ee <+124>:   mov    rax,QWORD PTR [rdx+rax*1]
   0x00005555555548f2 <+128>:   lea    rsi,[rip+0x1c6]        # 0x555555554abf
   0x00005555555548f9 <+135>:   mov    rdi,rax
   0x00005555555548fc <+138>:   call   0x5555555546d0 <strcmp@plt>
   0x0000555555554901 <+143>:   test   eax,eax
   0x0000555555554903 <+145>:   jne    0x555555554913 <main+161>
   0x0000555555554905 <+147>:   lea    rdi,[rip+0x1d5]        # 0x555555554ae1
   0x000055555555490c <+154>:   call   0x5555555546b0 <puts@plt>
   0x0000555555554911 <+159>:   jmp    0x555555554941 <main+207>
   0x0000555555554913 <+161>:   mov    eax,0x0
   0x0000555555554918 <+166>:   call   0x55555555481a <next_destination>
   0x000055555555491d <+171>:   mov    rbx,rax
--Type <RET> for more, q to quit, c to continue without paging--c
   0x0000555555554920 <+174>:   mov    eax,0x0
   0x0000555555554925 <+179>:   call   0x55555555481a <next_destination>
   0x000055555555492a <+184>:   mov    rdx,rbx
   0x000055555555492d <+187>:   mov    rsi,rax
   0x0000555555554930 <+190>:   lea    rdi,[rip+0x1b5]        # 0x555555554aec
   0x0000555555554937 <+197>:   mov    eax,0x0
   0x000055555555493c <+202>:   call   0x5555555546c0 <printf@plt>
   0x0000555555554941 <+207>:   add    QWORD PTR [rbp-0x18],0x1
   0x0000555555554946 <+212>:   cmp    QWORD PTR [rbp-0x18],0x5
   0x000055555555494b <+217>:   jbe    0x5555555548ac <main+58>
   0x0000555555554951 <+223>:   lea    rdi,[rip+0x1a0]        # 0x555555554af8
   0x0000555555554958 <+230>:   mov    eax,0x0
   0x000055555555495d <+235>:   call   0x5555555546c0 <printf@plt>
   0x0000555555554962 <+240>:   lea    rax,[rbp-0x20]
   0x0000555555554966 <+244>:   mov    rsi,rax
   0x0000555555554969 <+247>:   lea    rdi,[rip+0x1b5]        # 0x555555554b25
   0x0000555555554970 <+254>:   mov    eax,0x0
   0x0000555555554975 <+259>:   call   0x5555555546f0 <__isoc99_scanf@plt>
   0x000055555555497a <+264>:   lea    rdi,[rip+0x1af]        # 0x555555554b30
   0x0000555555554981 <+271>:   mov    eax,0x0
   0x0000555555554986 <+276>:   call   0x5555555546c0 <printf@plt>
   0x000055555555498b <+281>:   lea    rax,[rbp-0x28]
   0x000055555555498f <+285>:   mov    rsi,rax
   0x0000555555554992 <+288>:   lea    rdi,[rip+0x18c]        # 0x555555554b25
   0x0000555555554999 <+295>:   mov    eax,0x0
   0x000055555555499e <+300>:   call   0x5555555546f0 <__isoc99_scanf@plt>
   0x00005555555549a3 <+305>:   mov    eax,0x0
   0x00005555555549a8 <+310>:   call   0x55555555481a <next_destination>
   0x00005555555549ad <+315>:   mov    rdx,rax
   0x00005555555549b0 <+318>:   mov    rax,QWORD PTR [rbp-0x20]
   0x00005555555549b4 <+322>:   cmp    rdx,rax
   0x00005555555549b7 <+325>:   jne    0x5555555549db <main+361>
   0x00005555555549b9 <+327>:   mov    eax,0x0
   0x00005555555549be <+332>:   call   0x55555555481a <next_destination>
   0x00005555555549c3 <+337>:   mov    rdx,rax
   0x00005555555549c6 <+340>:   mov    rax,QWORD PTR [rbp-0x28]
   0x00005555555549ca <+344>:   cmp    rdx,rax
   0x00005555555549cd <+347>:   jne    0x5555555549db <main+361>
   0x00005555555549cf <+349>:   lea    rdi,[rip+0x18a]        # 0x555555554b60
   0x00005555555549d6 <+356>:   call   0x5555555546b0 <puts@plt>
   0x00005555555549db <+361>:   lea    rdi,[rip+0x1c6]        # 0x555555554ba8
   0x00005555555549e2 <+368>:   call   0x5555555546b0 <puts@plt>
   0x00005555555549e7 <+373>:   mov    eax,0x0
   0x00005555555549ec <+378>:   add    rsp,0x38
   0x00005555555549f0 <+382>:   pop    rbx
   0x00005555555549f1 <+383>:   pop    rbp
   0x00005555555549f2 <+384>:   ret    
End of assembler dump.

Some interesting instructions to point out here. At main+259 and main+300, we have scanf function calls. This is where the program gets our input for the x and y coordinates. At main+322 and main+344, we have comparisons done between some value (rdx) and our inputs (rax).

Let's go ahead and set breakpoints at main+322 and main+344 and continue execution of our program with c. We can enter in whatever data we want when the scanf function gets our input for now, since we'll change it later in the debugger. When we approach the breakpoint, we'll find out what our input (rax) is being compared to (rdx) by having a look at all of the registers. We can get information about registers using info registers, or i r for short.

The program is performing a comparison between our input, decimal 123 or hex 0x7b, and the decimal 191410283849669 or hex 0xae162df9a7c5. The comparison between these will obviously result in "not equal", to which we can expect the following instruction located on main+325 to jump execution to main+361 and leave the program without giving us our flag. We can't let that happen, so let's ensure that the comparison evaluates to "equal."

We're going to directly set the rax register equal to the value of the rdx register using set. Then, we're going to continue execution of the program until the next breakpoint, at which we'll do the same thing.

We got it!

Method 2: Jumping Over Comparisons

Instead of ensuring that the comparisons are equal to each other, we can straight up just jump over them using jump, essentially skipping them and going straight to the part of the program that prints us our flag.

We're going to, once again, set breakpoints at main+322 and main+344, as these are where our comparisons are occurring.

However, immediately after approaching a breakpoint, we're going to jump over the following jne instructions located on main+325 and main+347 to the following instructions located on main+327 and main+349, respectively.

And just like that, we have the flag.

Method 3: Strings

This one is less fun than the other two, but hey -- it works. A program file doesn't just contain machine instructions, but it also contains other data such as as the things that the instructions might print to the screen. We can use the strings utility to extract anything remotely human-readable and not machine jargon. We can use this in conjunction with grep to find the flag. We know that the flag is in some sort of CTF{} format, so we can specify that and the .* wildcard (meaning "anything") to come up with an expression for the flag.

Less fun, but it works.

Flag

CTF{welcome_to_googlectf}

Next Stop

Next stop: Satellite (Blue)

Original writeup (https://github.com/shawnduong/ctf-writeups/blob/master/2019-GOOGLE/beginners-quest/day0-enter-space-time-coordinates.md).