n1ctf 2020 逆向wp

oflo

// TODO

easyapk

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import base64
import hashlib
import random,string
from Crypto.Cipher import AES
from math import *
from pwn import *
import string
import base64
import ctypes
import time

s = 'n1ctf{17b87f9aae8933ef'
print(s+'a'*(38-len(s))+'}')
print(len(s)-6)
a = 'jZe3yJG3zJLHywu4otmZzwy'
tab = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-'
rtab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
d = {}
for i in range(len(tab)):
d[tab[i]] = rtab[i]
ra = ''
for i in a:
ra+=d[i]
ra+='='
flag1 = base64.b64decode(ra.encode('utf-8'))
print('flag1:',flag1)

iv = b'17b87f9aae8933ef'
key = b'\'17b87f9aae8933efn1ctf{}'
cipher = bytes([0xA5, 0xA4, 0x4C, 0xD, 0xD2, 0x52, 0x1E, 0x63, 0x54, 0xC5, 0x29, 0xFA,0xE4, 0xEC, 0x1F, 0x27,0x52, 0xD2, 0xF1, 0xB7, 0xE4, 0x1C, 0x61, 0x42, 0x77, 0x9F, 0x5D, 0xA1, 0x87, 0xA, 0xEC, 0x55])
aes = AES.new(mode=AES.MODE_CBC,iv=iv,key=key)
# 03b5029f16f7e605
print(aes.decrypt(cipher))
print('n1ctf{'+str(flag1,encoding='utf-8')+'03b5029f16f7e605}')

hook脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import frida,sys

def on_message(message,data):
print(message)
if message['type']=='send':
print('[*] {0}'.format(message['payload']))

if __name__=="__main__":
jscode = ''
with open('1.jsx','r') as f:
jscode = f.read()
p = frida.get_usb_device().attach('com.nu1l.ctf')
script = p.create_script(jscode)
script.on('message',on_message)
script.load()
sys.stdin.read()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
function print_string(offset) {
var module = Process.findModuleByName("libnative-lib.so")
var base = module.base;
console.log(ptr(base.add(ptr(offset))).readCString());
}
function hook_native() {
var module = Process.findModuleByName("libnative-lib.so")
var base = module.base;
var sub_12930 = base.add(0x12930);
Interceptor.attach(sub_12930, {
onEnter: function(args) {
this.arg0 = args[0];
console.log("sub_12930 onEnter:", hexdump(this.arg0), "\r\n");
}, onLeave: function(retval) {
console.log("sub_12930 onLeave:", hexdump(retval));
}
});
var sub_122A0 = base.add(0x122A0);
Interceptor.attach(sub_122A0, {
onEnter: function(args) {
this.arg0 = args[0]
this.arg1 = args[1]
this.arg2 = args[2]
console.log("sub_122A0 onEnter: ",ptr(this.arg0).readCString(),ptr(this.arg1).readCString(),ptr(this.arg2).readCString())
}, onLeave: function(retval) {
console.log("sub_122A0 onLeave:", hexdump(retval))
}
});
}

function main() {
hook_native();
}
setImmediate(main);

Oh my julia

对于JIT型语言的技巧,就是找到编译后的代码

  1. 当程序要求输入时断下

  2. 单步执行直到程序输出东西

  3. 在输入/常量flag部分下硬件断点

之后就可以把编译后的代码dump下来用于后续分析

// TODO 果然还是基本功,先做点简单的

BabyOS

binwalk使用指南

  • 查看固件

    1
    binwalk 文件名
  • 解压压缩包

    1
    2
    binwalk -e 文件名 # 解压压缩包
    binwalk -eM -d depth 文件名 # M表示递归解压,depth为深度,不指定默认为8
  • 解压指定类型文件

    1
    binwalk -e -D=type 文件名 # type是要解压的类型,我已知的elf,jpeg

wp

xbook2操作系统是一个大学生写的,tqlOrzzzzzz。这个操作系统的信息可以使用strings看出来,其中有

1
1564: D:/Developmemts/github/xbook2/src/include/xbook/schedule.h

从而找到这个操作系统相关的信息

运行操作系统,列出文件,发现一个n1ctf程序,可以运行。这个程序位于xbook2-file1.img,使用binwalk解出来

但是程序似乎是加密的。

使用binwalk扫第一个a.img,解出一个程序,丢进IDA,发现这是一个操作系统程序(因为看见kernel等字样了)

然后找到一个do_execute函数,这个函数里面发现了加密逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
v7 = sys_open(v17, 1, 0);
if ( v7 < 0 )
return -1;
v19 = sys_open("/tmp/decrypt", 28, 0);
if ( v19 >= 0 )
{
v8 = sys_lseek(v7, 0, 2);
sys_lseek(v7, 0, 0);
v9 = kmalloc(v8);
v10 = v9;
if ( v9 )
{
if ( sys_read(v7, v9, v8) == v8 )
{
v12 = strlen("xpawqejc4654wqqwe123%#%3213");
if ( v8 )
{
v13 = 0;
do
{
*(_BYTE *)(v10 + v13) ^= aXpawqejc4654wq[v13 % v12] ^ (unsigned __int8)v13;
++v13;
}
while ( v13 != v8 );
}
if ( sys_write(v19, v10, v8) == v8 )
{
kfree(v10);
sys_close(v19);
sys_close(v7);
v14 = sys_open("/tmp/decrypt", 1, 0);
if ( v14 >= 0 )用

使用这个解密出n1ctf程序

n1ctf程序

// TODO

BabyCompiler

// TODO

Fixed Camera

是一个il2cpp程序

il2cpp编译后的逻辑位于GameAssembly.dll中,但是不知道函数都是啥,而且函数很多。

使用il2cppdump解出Assembly-Csharp.dll,可以找到函数的函数名和VA,再回头看GameAssembly.dll,可以分析。

patch cam的Update函数,把负数的限制扩大,然后就可以获得flag了

在移动过程中可能有加密,但是到-50时出现flag

n1ctf{enbrypt_value}

rrr

// 此题看不懂

N1vault

// TODO