用手机打 CTF 种什么体验

尝试不用电脑,只拿一台iPhone去参加看雪CTF2020 (娱乐向)
视频地址: https://www.bilibili.com/video/BV1Da4y1p7F3
背景
最近 iSH 在 Apple Store 上架了,之前一直抢不到 testflight 的配额,难得强管控的苹果会让这种 Terminal 类的应用发布,所以第一时间下载来玩玩。测试之后发现可以当做是一个简单的 Linux 虚拟机,至少常用的命令都没什么问题,正好看到看雪论坛有个 CTF,于是就试一下,能不能用手机来打一局 CTF :)
环境
iSH 是一个开源的 Terminal Emulator,在 iOS 中运行,使用用户态的 x86 指令模拟以及 syscall 翻译实现。iSH 中使用的是 Alphine Linux 镜像,用过 Docker 的应该都不会陌生。Alphine 是个非常轻量级的 Linux 发行版,在官网上可以直接下载各个平台预编译的镜像,平时有测试内核需求又不满足于 ramfs 的可以使用下载的镜像进行方便测试。
在 iSH 中已经有了一个简单的 Alphine 环境,可能是是因为苹果商店审核的原因,在其中并没有预置包管理工具。我们可以下载一个完整的 iso 重新挂载,但是有更简单的方法,直接从 Alphine Packages 中下载静态编译版本的 apk-tools-static:
wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/main/x86/apk-tools-static-2.10.5-r1.apk
tar -zxvf apk-tools-static-2.10.5-r1.apk
./sbin/apk.static -X https://mirrors.tuna.tsinghua.edu.cn --initdb add apk-tools
apk update
rm -rf ./sbin
我们用下载的 apk-tools-static 来安装 apk-tools,然后包管理工具 apk 就可以正常使用了。如果初始化的时候没有指定镜像源,可以使用下面的命令修改为清华大学的镜像源,加快国内的访问速度:
sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories
之后需要的工具就可以自行安装了,我这里只需要 radare2 和 Python:
apk add radare2
apk add python3
题目是看雪 CTF2020 的签到题: https://ctf.pediy.com/game-season_fight-158.htm
Write Up
解题过程在文章开头的视频中已经可以看到了,这里还是用文字介绍下解题思路。
首先 rabin2 查看目标程序的信息:
$ rabin2 -I kctf2020.exe
arch x86
baddr 0x140000000
binsz 12288
bintype pe
bits 64
canary false
retguard false
class PE32+
cmp.csum 0x0000bcb6
compiled Thu Nov 12 03:49:32 2020
crypto false
dbg_file D:\Users\admin\Documents\Visual Studio 2015\Projects\ctf2020\ConsoleApplication1\x64\Release\ConsoleApplication1.pdb
endian little
havecode true
hdr.csum 0x00000000
guid 4EF50FB8F5E74CC481D01589FC111B1A1
laddr 0x0
lang c
linenum false
lsyms false
machine AMD 64
maxopsz 16
minopsz 1
nx true
os windows
overlay false
cc ms
pcalign 0
pic true
relocs false
signed false
sanitiz false
static false
stripped false
subsys Windows CUI
va true
可以看到是 PE64 的的程序,鉴于是签到题,所以就直接逆向分析了:
$ r2 kctf2020.exe
-- 💺
[0x14000154c]> s main
[0x140001000]> af
[0x140001000]> pd 20
;-- section..text:
┌ 459: int main (int argc, char **argv, char **envp);
│ bp: 7 (vars 7, args 0)
│ sp: 14 (vars 14, args 0)
│ rg: 0 (vars 0, args 0)
│ 0x140001000 4055 push rbp ; [00] -r-x section size 8192 named .text
│ 0x140001002 488dac24c0fe. lea rbp, [rsp - 0x140]
│ 0x14000100a 4881ec400200. sub rsp, 0x240
│ 0x140001011 488b05e82f00. mov rax, qword [section..data] ; [0x140004000:8]=0x2b992ddfa232 ; "2\xa2\xdf-\x99+"
│ 0x140001018 4833c4 xor rax, rsp
│ 0x14000101b 488985300100. mov qword [var_130h], rax
│ 0x140001022 33d2 xor edx, edx
│ 0x140001024 488d4c2430 lea rcx, [var_30h]
│ 0x140001029 41b800010000 mov r8d, 0x100 ; 256
│ 0x14000102f e8ce0e0000 call 0x140001f02
│ 0x140001034 33d2 xor edx, edx
│ 0x140001036 488d4d30 lea rcx, [var_bp_30h]
│ 0x14000103a 41b800010000 mov r8d, 0x100 ; 256
│ 0x140001040 e8bd0e0000 call 0x140001f02
│ 0x140001045 488d0dd42100. lea rcx, str.KCTF_2020 ; 0x140003220 ; "KCTF 2020!\n"
│ 0x14000104c e8ff010000 call 0x140001250
│ 0x140001051 488d0dd82100. lea rcx, str.http:__bbs.pediy.com ; 0x140003230 ; "http://bbs.pediy.com\n"
│ 0x140001058 e8f3010000 call 0x140001250
│ 0x14000105d 488d0de42100. lea rcx, str.Please_input_your_flag: ; 0x140003248 ; "Please input your flag: "
│ 0x140001064 e8e7010000 call 0x140001250
在 0x140001250
地址处经常有调用,根据参数可以猜测是打印函数,验证一下:
[0x140001000]> s 0x140001250
[0x140001250]> af
[0x140001250]> pdf
; CALL XREFS from main @ 0x14000104c, 0x140001058, 0x140001064, 0x14000119b, 0x1400011ab
┌ 85: int printf (const char *format);
│ ; var int64_t var_20h_2 @ rsp+0x20
│ ; var int64_t var_8h @ rsp+0x50
│ ; var int64_t var_10h @ rsp+0x58
│ ; var int64_t var_18h @ rsp+0x60
│ ; var int64_t var_20h @ rsp+0x68
│ ; arg int64_t arg1 @ rcx
│ ; arg int64_t arg2 @ rdx
│ ; arg int64_t arg3 @ r8
│ ; arg int64_t arg4 @ r9
│ 0x140001250 48894c2408 mov qword [var_8h], rcx ; arg1
│ 0x140001255 4889542410 mov qword [var_10h], rdx ; arg2
│ 0x14000125a 4c89442418 mov qword [var_18h], r8 ; arg3
│ 0x14000125f 4c894c2420 mov qword [var_20h], r9 ; arg4
│ 0x140001264 53 push rbx
│ 0x140001265 56 push rsi
│ 0x140001266 57 push rdi
│ 0x140001267 4883ec30 sub rsp, 0x30
│ 0x14000126b 488bf9 mov rdi, rcx
│ 0x14000126e 488d742458 lea rsi, [var_10h]
│ 0x140001273 b901000000 mov ecx, 1
│ 0x140001278 ff150a1f0000 call qword [sym.imp.api_ms_win_crt_stdio_l1_1_0.dll___acrt_iob_func] ; [0x140003188:8]=0x3a98 reloc.api_ms_win_crt_stdio_l1_1_0.dll___acrt_iob_func
│ 0x14000127e 488bd8 mov rbx, rax
│ 0x140001281 e8baffffff call fcn.140001240
│ 0x140001286 4533c9 xor r9d, r9d
│ 0x140001289 4889742420 mov qword [var_20h_2], rsi
│ 0x14000128e 4c8bc7 mov r8, rdi
│ 0x140001291 488bd3 mov rdx, rbx
│ 0x140001294 488b08 mov rcx, qword [rax]
│ 0x140001297 ff15e31e0000 call qword [sym.imp.api_ms_win_crt_stdio_l1_1_0.dll___stdio_common_vfprintf] ; [0x140003180:8]=0x3aaa reloc.api_ms_win_crt_stdio_l1_1_0.dll___stdio_common_vfprintf
│ 0x14000129d 4883c430 add rsp, 0x30
│ 0x1400012a1 5f pop rdi
│ 0x1400012a2 5e pop rsi
│ 0x1400012a3 5b pop rbx
└ 0x1400012a4 c3 ret
果然是打印函数,直接重命名一下,清爽一些: