Page MenuHomedesp's stash

corctf22.md
No OneTemporary

corctf22.md

### microsoft <3 linux
thought it was a binfmt_misc thing with wsl considering the name, so i just ran it in wsl for a bit
except IDA crashes every time i try to debug it and core dumps arent that helpful either lmao
[@Robert](https://maplebacon.org/authors/Nneonneo/) helped cleaning the elf up for a bit but i realized it really is just a small program
if i just paid more attention i wouldve realized its bitwise rotation from the start lol
was finding reimplementations rol/ror in python but had a few duds before i found one that works
that only got me half the flag though so i had to figure out whats left
in the meantime [@Robert](https://maplebacon.org/authors/Nneonneo/) spotted the `$` at the end of the string after i pointed out i cant run it on windows since its not compatible
so he instantly concluded that this is a DOS COM file and indeed it is
except binja's decompilation with the DOS plugin really is not that good so i just used IDA and manually reversed it from assembly lol
turns out its just a simple 0xD xor anyway
either way flage `corctf{3mbr4c3,3xt3nd,3Xt1ngu15h!!1}`
```py
rol = lambda val, r_bits, max_bits: (val << r_bits%max_bits) & (2**max_bits-1) | ((val & (2**max_bits-1)) >> (max_bits-(r_bits%max_bits)))
ror = lambda val, r_bits, max_bits: ((val & (2**max_bits-1)) >> r_bits%max_bits) | (val << (max_bits-(r_bits%max_bits)) & (2**max_bits-1))
#ELF
print(''.join([chr(rol(i, 3, 8)) for i in b'l\xedNl\x8e\xccof\xadLN\x86lf\x85f\x0f\x8e>ci!>Uy<cjx<8e,,<p'[:18]]), end='')
#COM 16 bit
print(''.join([chr(i ^ 0xD) for i in b'l\xedNl\x8e\xccof\xadLN\x86lf\x85f\x0f\x8e>ci!>Uy<cjx<8e,,<p'[18:]]))
```
### msfrob
[@Em]() was looking at it and got me interested coz i see dlopen
but she said she couldnt even get it to run so i thought there might be some anti debugging thing
turns out its just coz if we pass nothing to the parameters thats supposed to be the flag to be checked it just terminates lol
so with that i just looked at the functions and realized they are all jump outs which means the got and stuff is kinda screwed
not the first time ive encountered this tho i think last time was cyber apoc's shuffleme
so same deal dynamically trace the function resolving and manually name it again
eventually after a bit of renaming i realized its just zlib and aes 256 cbc
though i wasnt sure what the loop was doing coz the code was still messy so i had to tidy the stack variables up
IDA's local type -> insert C declaration really helped for the `z_stream` struct
[@Angus](https://maplebacon.org/authors/alueft/) was helping on the side testing out different stuff but nothing really worked
until i realized it really is just running the AES 20 times so i looked to see if my codes for that was wrong since i can only run it once before dying
turns out i just forgot to put AES initialization inside the loop lol which means its considered the same stream which ofc aint gonna work
anyway flage again `corctf{why_w0u1d_4ny0n3_us3_m3mfr0b??}`
i completely didnt touch memfrob aside from the chall desc that [@Angus](https://maplebacon.org/authors/alueft/) pointed out lmao
```py
import zlib
import base64
from Crypto.Cipher import AES
data = base64.b64decode('TO80+tElRUvnrZnEsdf2LFvzE7/MAx0WgdtQOKi23SCQKm6i7/5rj9uAb3B063025NyH8yDr5Q8+KDVYrQfSPdhdQTVeT0GbkYXhXBi49lrfCDUxBNLgRGT8BsbWW5ggTxweuCDVntqB1jZbVWCoLPLaV5LJ4BTwQ0suEdNwZ6hVCH3Hdk936L7zGQSEsqAg3EzSyJQXm3VPeDU15mJ0LQyoNPGQqf1Z1PgkuTuUvXnHeLlWweO2Lhc6MvlOR/kJxOj6SVNqC7k2CytcyfM5Y7PRrHBs8UZCvAuROmSVd+wkAWTSmOG/OBfU0DkWEx00pBr6M1+IIdVcTr8zneEqzEcVA52mhTYtbTEBPZUI3HLT9vdlt8CVXfTJp/rc71E2wR3mCOuK7F3JWj3TmqatKJkkiJJALasSWfiER7K5SPePHjJkuiTSPfPEhL3S4QEHoXYYRR5UkZMRbkFUfkDnAg==')
print(len(data))
key = b'\xd4\xf5\xd9g\x15/w\x7fl|Fs\xf6\xf0\x92\xf0wP;0\x0c\x87\x8a\r\x9c\x1dr\xa2eF\xc8\xdc'
print(len(key))
iv = b'\0'*16
for i in range(20):
c = AES.new(key, AES.MODE_CBC, iv)
print(i)
strm = c.decrypt(data)
print(strm)
data = zlib.decompress(strm)
print('\n', data, sep='')
#data = bytes([x ^ 42 for x in data])
with open('dump', 'wb') as wb:
print(data)
wb.write(data)
#oops too late
desc = bytes.fromhex('6b0a444558474b460a5a58454d584b470a5f5943444d0a444558474b460a4d464348490a4c5f44495e4345445904')
desc = bytes([x ^ 42 for x in desc])
print(desc)
```
### turbocrab
beeg rust binary that looks like its crafting some sort of shellcode and executing it?
dont care, i can just breakpoint after it finishes crafting the shellcode and jump to it
the shellcode looks quite confusing though with IDA's decompiler not working that well
and i cant really use binja for it coz i dont really know how to use binjas debugger still yet and the shellcode has to be dynamically obtained
so i tried to look for places that might be potential instruction counting sites and see if there are patterns considering it looks like its AND-ing until one of the recursion fails which will return 0 for the entire chain
but somehow my breakpoints were all not working
after a bit of digging around and finding alternatives like tracepoints or even counting steps a thought came to my mind
would it be because im lacking write perms for the new page
so i patched mprotect and breakpoints actually work now so that saved a lot of time
eventually i found a `test al al` location that looks kinda interesting and i wanna automate it to see if it really can be instruction counted
but pwntools was having a field day with my usual gdb method by breaking the child process read() that it kept saying `SIGTTIN`
had to mess around quite a bit again here too trying out temp files as stdin or in memory buffers like StringIO but none worked until i changed stdin to PTY
still there was quite a bit of wackiness when it comes to communicating with the process and my instruction counting script ended up only working 50% of the time
but theres not really that many false positives so its just a big waiting game
eventually some false positives did pop up but they were scarse enough that i can just reason my way through the flag
for some reason using DEBUG prints for pwntools also helped in stabilizing the script too lol
either way aside from the last char of the flag which i didnt put in the dictionary until i manually submitted the flags to the platform (i forgot the binary was a flag checker itself lmfao) i realized it was a question mark
anyway heres flage lol `corctf{x86_j1t_vm_r3v3rs1ng?}` took way too long
also another chall that i didnt touch what they expected me to touch again lmao
```py
from pwn import *
import string
import io
#context.log_level = 'ERROR'
flag = 'corctf{x86_j1t_vm_r3v3rs1ng'
while len(flag) < 29:
#val = {}
for c in string.printable:
p = process(['/usr/bin/gdb', '-q', './turbocrab'], stdin=PTY)
p.sendline(b'start')
p.recvuntil(b'turbocrab::main')
p.sendline(b'catch syscall read') #need to break for mprotect to be run before breakpoint in shellcode
p.recvuntil(b'(gdb) ')
p.sendline(b'continue')
p.recvuntil(b'(gdb) ')
p.sendline(b'continue')
#p.interactive()
p.send(flag + c) #sendline's \n screws up the counter sometimes
p.recvuntil(b'(gdb) ')
p.sendline(b'i r rax')
r = p.recvuntil(b'(gdb) ')
print(r)
p.sendline(b'b *0x00007ffff7ffa228') #gdb is pie disabled; this seems to be where the 1s change to 0s and the recursion ends
p.recvuntil(b'(gdb) ')
p.sendline(b'continue')
count = 0
try:
while True:
print(count)
p.sendline(b'continue')
r = p.recvuntil(b'(gdb) ')
print(r)
if b'incorrect' in r:
p.close()
break
count += 1
except EOFError:
p.close()
print(count, c, flag)
# if count > len(flag) + 2:
# flag += c
# break
#val[c] = count
#print(max(val, key=val.get))
```

File Metadata

Mime Type
text/x-python
Expires
Mon, Aug 4, 8:35 PM (19 h, 20 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
33/8a/98b571effc80f9ca80c78e591b0e

Event Timeline