【CTF对抗-hack.lu 2024 Getting into Shape wp】此文章归类为:CTF对抗。
rust
通过wasm_bindgen
编译wasm
,一些有趣的小机制,算是一个彩蛋,如果你感兴趣,兴许可以出个有趣的小题目或者实现一个神秘的小功能。题目附件给了一个tff(TrueTypeFont)文件,在该文件中嵌入一个wasm, 该wasm文件的源码通过rust编写,该代码写了flag的checker部分,checker部分算法使用chacha20加密,通过字体的控制完成映射,并显示,显示结果:
flag错时:
flag对时:
首先将ttf文件放到010 editor中观察
在ttf最后一个成员gasp 后往下的一部分 出现asm(wasm的magic number)
推测这里是嵌入了wasm文件(实际就是harfbuzz中可选的wasm shaper)
使用python脚本提取:
1 2 3 4 5 6 7 | with open ( 'challenge.ttf' , 'rb' ) as file : read_bytes = file .read() with open ( 'challenge.wasm' , 'wb' ) as ff: start = 0x1eb9c end = start + 0x12841b ff.write(read_bytes[start:end]) |
end的选取 在使用wasm2wat等工具时会报错,根据报错逐渐调整end
可以看到结尾的‘字符串’是/+.\S*$/的格式, 按照这个规律challenge的wasm的end应在这里:
当然也可以自己编译一个wasm比较一下,下面是我自己编译的demo.wasm(wasm-pack 构建rust项目)[[how to Compile a WebAssembly module from rust](https://developer.mozilla.org/en-US/docs/WebAssembly/Rust_to_Wasm)]
对于wasm的文件处理可以使用wasm2c或者wasm2js
这里使用wasm2c 对wasm文件进行处理
实际不管使用wasm2c 还是 wasm2js, 代码形式和汇编差不多,并没有多少简化
wasm2c反编译出来的数据是16进制显示,wasm2js是base64编码,这对于我们分析字符串都不方便,这里使用wasm2wat查看dcmp文件中的字符串:
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 | data d_Usersmsanftcargoregistrysrci(offset: 1048576) = "/Users/msanft/.cargo/registry/src/index.crates.io-6f17d22bba15001f/reg" "ex-automata-0.4.8/src/util/pool.rs\00\00\10\00h\00\00\00=\02\00\00\1c\00" "\00\00\00\00\00\00\04\00\00\00\04\00\00\00\01\00\00\00/Users/msanft/.c" "argo/registry/src/index.crates.io-6f17d22bba15001f/regex-automata-0.4." "8/src/util/pool.rs\88\00\10\00h\00\00\00^\02\00\00\1c\00\00\00\88\00\10" "\00h\00\00\00k\02\00\002\00\00\00\88\00\10\00h\00\00\00\01\03\00\00\15" "\00\00\00StreamCipherError\00\00\00expand 32-byte kcalled `Result::unw" "rap()` on an `Err` valueMq\ac\14v\b1\9al\aa\ec\86qA\12\f3\bfkr\f0\a5kz" "\fc\d1\1aR\9c\d3\ba\00\00\00\00\00\00\00\00\01\00\00\00\02\00\00\00/Us" "ers/msanft/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cipher" "-0.4.4/src/stream.rs\00\00\00\9c\01\10\00]\00\00\00x\00\00\00'\00\00\00" "flag\{([^{}]*)\}src/lib.rs\00\00\1c\02\10\00\0a\00\00\00\18\00\00\00-\00" "\00\00nah\f0\9f\98\90\f0\9f\98\90yasss!!\f0\9f\98\8c\f0\9f\92\85\00\00" "\03\00\00\00\0c\00\00\00\04\00\00\00\04\00\00\00\1c\02\10\00\0a\00\00\00" "\15\00\00\00.\00\00\00Couldn't copy buffer contents\00\00\00t\02\10\00" "\1d\00\00\00/Users/msanft/Documents/Documents - Moritz\e2\80\99s MacBo" "ok Pro/harfbuzz-wasm-examples/harfbuzz-wasm/src/lib.rs\00\00\9c\02\10\00" "j\00\00\00>\01\00\00;\00\00\00Couldn't set buffer contents\18\03\10\00" "\1c\00\00\00\9c\02\10\00j\00\00\00^\01\00\00\11\00\00\00regex: thread " "ID allocation space exhausted\00L\03\10\00+\00\00\00/Users/msanft/.car" "go/registry/src/index.crates.io-6f17d22bba15001f/regex-automata-0.4.8/" "src/util/pool.rs\80\03\10\00h\00\00\00^\01\00\00\11\00\00\00\00\00\00\00" "\04\00\00\00\04\00\00\00\07\00\00\00Error\00\00\00\08\00\00\00\0c\00\00" "\00\04\00\00\00\09\00\00\00\0a\00\00\00\0b" ; |
可以看到有关于flag的正则表达式:flag{([^{}]*)
关键的.rs,如arfbuzz-wasm-examples/harfbuzz-wasm/src/lib.rs, google一下就会知道,这是github项目,在该仓库中我可以找到在m1上可以使用harfbuzz的工具:https://github.com/harfbuzz/harfbuzz-wasm-examples/tree/main/fontgoggles-wasm-m1
正是前面提到的查看flag checker运行结果的程序
这里查看wasm2c反编译出来的c语言,太长,太多,总共有41万行,找个函数引用vscode都会卡住
人工分析显然是不太可能,这是我编写了一个对“flag{([^{}]*)”所在缓冲区的引用搜集
在wasm2c该缓冲区为:
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | static const u8 data_segment_data_w2c_challenge_d0[] = { 0x2f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x6d, 0x73, 0x61, 0x6e, 0x66, 0x74, 0x2f, 0x2e, 0x63, 0x61, 0x72, 0x67, 0x6f, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, 0x73, 0x72, 0x63, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x63, 0x72, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x69, 0x6f, 0x2d, 0x36, 0x66, 0x31, 0x37, 0x64, 0x32, 0x32, 0x62, 0x62, 0x61, 0x31, 0x35, 0x30, 0x30, 0x31, 0x66, 0x2f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x2d, 0x61, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x61, 0x2d, 0x30, 0x2e, 0x34, 0x2e, 0x38, 0x2f, 0x73, 0x72, 0x63, 0x2f, 0x75, 0x74, 0x69, 0x6c, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2e, 0x72, 0x73, 0x00, 0x00, 0x10, 0x00, 0x68, 0x00, 0x00, 0x00, 0x3d, 0x02, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x6d, 0x73, 0x61, 0x6e, 0x66, 0x74, 0x2f, 0x2e, 0x63, 0x61, 0x72, 0x67, 0x6f, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, 0x73, 0x72, 0x63, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x63, 0x72, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x69, 0x6f, 0x2d, 0x36, 0x66, 0x31, 0x37, 0x64, 0x32, 0x32, 0x62, 0x62, 0x61, 0x31, 0x35, 0x30, 0x30, 0x31, 0x66, 0x2f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x2d, 0x61, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x61, 0x2d, 0x30, 0x2e, 0x34, 0x2e, 0x38, 0x2f, 0x73, 0x72, 0x63, 0x2f, 0x75, 0x74, 0x69, 0x6c, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2e, 0x72, 0x73, 0x88, 0x00, 0x10, 0x00, 0x68, 0x00, 0x00, 0x00, 0x5e, 0x02, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x88, 0x00, 0x10, 0x00, 0x68, 0x00, 0x00, 0x00, 0x6b, 0x02, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x88, 0x00, 0x10, 0x00, 0x68, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x20, 0x33, 0x32, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x20, 0x6b, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x60, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x3a, 0x3a, 0x75, 0x6e, 0x77, 0x72, 0x61, 0x70, 0x28, 0x29, 0x60, 0x20, 0x6f, 0x6e, 0x20, 0x61, 0x6e, 0x20, 0x60, 0x45, 0x72, 0x72, 0x60, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4d, 0x71, 0xac, 0x14, 0x76, 0xb1, 0x9a, 0x6c, 0xaa, 0xec, 0x86, 0x71, 0x41, 0x12, 0xf3, 0xbf, 0x6b, 0x72, 0xf0, 0xa5, 0x6b, 0x7a, 0xfc, 0xd1, 0x1a, 0x52, 0x9c, 0xd3, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x6d, 0x73, 0x61, 0x6e, 0x66, 0x74, 0x2f, 0x2e, 0x63, 0x61, 0x72, 0x67, 0x6f, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, 0x73, 0x72, 0x63, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x63, 0x72, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x69, 0x6f, 0x2d, 0x36, 0x66, 0x31, 0x37, 0x64, 0x32, 0x32, 0x62, 0x62, 0x61, 0x31, 0x35, 0x30, 0x30, 0x31, 0x66, 0x2f, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x2d, 0x30, 0x2e, 0x34, 0x2e, 0x34, 0x2f, 0x73, 0x72, 0x63, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x72, 0x73, 0x00, 0x00, 0x00, 0x9c, 0x01, 0x10, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x66, 0x6c, 0x61, 0x67, 0x5c, 0x7b, 0x28, 0x5b, 0x5e, 0x7b, 0x7d, 0x5d, 0x2a, 0x29, 0x5c, 0x7d, 0x73, 0x72, 0x63, 0x2f, 0x6c, 0x69, 0x62, 0x2e, 0x72, 0x73, 0x00, 0x00, 0x1c, 0x02, 0x10, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x6e, 0x61, 0x68, 0xf0, 0x9f, 0x98, 0x90, 0xf0, 0x9f, 0x98, 0x90, 0x79, 0x61, 0x73, 0x73, 0x73, 0x21, 0x21, 0xf0, 0x9f, 0x98, 0x8c, 0xf0, 0x9f, 0x92, 0x85, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1c, 0x02, 0x10, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x75, 0x6c, 0x64, 0x6e, 0x27, 0x74, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x00, 0x00, 0x00, 0x74, 0x02, 0x10, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x2f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x6d, 0x73, 0x61, 0x6e, 0x66, 0x74, 0x2f, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x2d, 0x20, 0x4d, 0x6f, 0x72, 0x69, 0x74, 0x7a, 0xe2, 0x80, 0x99, 0x73, 0x20, 0x4d, 0x61, 0x63, 0x42, 0x6f, 0x6f, 0x6b, 0x20, 0x50, 0x72, 0x6f, 0x2f, 0x68, 0x61, 0x72, 0x66, 0x62, 0x75, 0x7a, 0x7a, 0x2d, 0x77, 0x61, 0x73, 0x6d, 0x2d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x68, 0x61, 0x72, 0x66, 0x62, 0x75, 0x7a, 0x7a, 0x2d, 0x77, 0x61, 0x73, 0x6d, 0x2f, 0x73, 0x72, 0x63, 0x2f, 0x6c, 0x69, 0x62, 0x2e, 0x72, 0x73, 0x00, 0x00, 0x9c, 0x02, 0x10, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x75, 0x6c, 0x64, 0x6e, 0x27, 0x74, 0x20, 0x73, 0x65, 0x74, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x10, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x5e, 0x01, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x72, 0x65, 0x67, 0x65, 0x78, 0x3a, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x20, 0x49, 0x44, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x65, 0x78, 0x68, 0x61, 0x75, 0x73, 0x74, 0x65, 0x64, 0x00, 0x4c, 0x03, 0x10, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x2f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x6d, 0x73, 0x61, 0x6e, 0x66, 0x74, 0x2f, 0x2e, 0x63, 0x61, 0x72, 0x67, 0x6f, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, 0x73, 0x72, 0x63, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x63, 0x72, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x69, 0x6f, 0x2d, 0x36, 0x66, 0x31, 0x37, 0x64, 0x32, 0x32, 0x62, 0x62, 0x61, 0x31, 0x35, 0x30, 0x30, 0x31, 0x66, 0x2f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x2d, 0x61, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x61, 0x2d, 0x30, 0x2e, 0x34, 0x2e, 0x38, 0x2f, 0x73, 0x72, 0x63, 0x2f, 0x75, 0x74, 0x69, 0x6c, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2e, 0x72, 0x73, 0x80, 0x03, 0x10, 0x00, 0x68, 0x00, 0x00, 0x00, 0x5e, 0x01, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, }; |
加载位置:
1 2 3 4 5 | static void init_memories(w2c_challenge* instance) { wasm_rt_allocate_memory(&instance->w2c_memory, 23, 65536, 0); LOAD_DATA(instance->w2c_memory, 1048576u, data_segment_data_w2c_challenge_d0, 1061); //.... } |
下面使用python脚本对1048576-101048576+1061处所有的引用进行提取
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | ss = [ 0x2f , 0x55 , 0x73 , 0x65 , 0x72 , 0x73 , 0x2f , 0x6d , 0x73 , 0x61 , 0x6e , 0x66 , 0x74 , 0x2f , 0x2e , 0x63 , 0x61 , 0x72 , 0x67 , 0x6f , 0x2f , 0x72 , 0x65 , 0x67 , 0x69 , 0x73 , 0x74 , 0x72 , 0x79 , 0x2f , 0x73 , 0x72 , 0x63 , 0x2f , 0x69 , 0x6e , 0x64 , 0x65 , 0x78 , 0x2e , 0x63 , 0x72 , 0x61 , 0x74 , 0x65 , 0x73 , 0x2e , 0x69 , 0x6f , 0x2d , 0x36 , 0x66 , 0x31 , 0x37 , 0x64 , 0x32 , 0x32 , 0x62 , 0x62 , 0x61 , 0x31 , 0x35 , 0x30 , 0x30 , 0x31 , 0x66 , 0x2f , 0x72 , 0x65 , 0x67 , 0x65 , 0x78 , 0x2d , 0x61 , 0x75 , 0x74 , 0x6f , 0x6d , 0x61 , 0x74 , 0x61 , 0x2d , 0x30 , 0x2e , 0x34 , 0x2e , 0x38 , 0x2f , 0x73 , 0x72 , 0x63 , 0x2f , 0x75 , 0x74 , 0x69 , 0x6c , 0x2f , 0x70 , 0x6f , 0x6f , 0x6c , 0x2e , 0x72 , 0x73 , 0x00 , 0x00 , 0x10 , 0x00 , 0x68 , 0x00 , 0x00 , 0x00 , 0x3d , 0x02 , 0x00 , 0x00 , 0x1c , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x04 , 0x00 , 0x00 , 0x00 , 0x04 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x2f , 0x55 , 0x73 , 0x65 , 0x72 , 0x73 , 0x2f , 0x6d , 0x73 , 0x61 , 0x6e , 0x66 , 0x74 , 0x2f , 0x2e , 0x63 , 0x61 , 0x72 , 0x67 , 0x6f , 0x2f , 0x72 , 0x65 , 0x67 , 0x69 , 0x73 , 0x74 , 0x72 , 0x79 , 0x2f , 0x73 , 0x72 , 0x63 , 0x2f , 0x69 , 0x6e , 0x64 , 0x65 , 0x78 , 0x2e , 0x63 , 0x72 , 0x61 , 0x74 , 0x65 , 0x73 , 0x2e , 0x69 , 0x6f , 0x2d , 0x36 , 0x66 , 0x31 , 0x37 , 0x64 , 0x32 , 0x32 , 0x62 , 0x62 , 0x61 , 0x31 , 0x35 , 0x30 , 0x30 , 0x31 , 0x66 , 0x2f , 0x72 , 0x65 , 0x67 , 0x65 , 0x78 , 0x2d , 0x61 , 0x75 , 0x74 , 0x6f , 0x6d , 0x61 , 0x74 , 0x61 , 0x2d , 0x30 , 0x2e , 0x34 , 0x2e , 0x38 , 0x2f , 0x73 , 0x72 , 0x63 , 0x2f , 0x75 , 0x74 , 0x69 , 0x6c , 0x2f , 0x70 , 0x6f , 0x6f , 0x6c , 0x2e , 0x72 , 0x73 , 0x88 , 0x00 , 0x10 , 0x00 , 0x68 , 0x00 , 0x00 , 0x00 , 0x5e , 0x02 , 0x00 , 0x00 , 0x1c , 0x00 , 0x00 , 0x00 , 0x88 , 0x00 , 0x10 , 0x00 , 0x68 , 0x00 , 0x00 , 0x00 , 0x6b , 0x02 , 0x00 , 0x00 , 0x32 , 0x00 , 0x00 , 0x00 , 0x88 , 0x00 , 0x10 , 0x00 , 0x68 , 0x00 , 0x00 , 0x00 , 0x01 , 0x03 , 0x00 , 0x00 , 0x15 , 0x00 , 0x00 , 0x00 , 0x53 , 0x74 , 0x72 , 0x65 , 0x61 , 0x6d , 0x43 , 0x69 , 0x70 , 0x68 , 0x65 , 0x72 , 0x45 , 0x72 , 0x72 , 0x6f , 0x72 , 0x00 , 0x00 , 0x00 , 0x65 , 0x78 , 0x70 , 0x61 , 0x6e , 0x64 , 0x20 , 0x33 , 0x32 , 0x2d , 0x62 , 0x79 , 0x74 , 0x65 , 0x20 , 0x6b , 0x63 , 0x61 , 0x6c , 0x6c , 0x65 , 0x64 , 0x20 , 0x60 , 0x52 , 0x65 , 0x73 , 0x75 , 0x6c , 0x74 , 0x3a , 0x3a , 0x75 , 0x6e , 0x77 , 0x72 , 0x61 , 0x70 , 0x28 , 0x29 , 0x60 , 0x20 , 0x6f , 0x6e , 0x20 , 0x61 , 0x6e , 0x20 , 0x60 , 0x45 , 0x72 , 0x72 , 0x60 , 0x20 , 0x76 , 0x61 , 0x6c , 0x75 , 0x65 , 0x4d , 0x71 , 0xac , 0x14 , 0x76 , 0xb1 , 0x9a , 0x6c , 0xaa , 0xec , 0x86 , 0x71 , 0x41 , 0x12 , 0xf3 , 0xbf , 0x6b , 0x72 , 0xf0 , 0xa5 , 0x6b , 0x7a , 0xfc , 0xd1 , 0x1a , 0x52 , 0x9c , 0xd3 , 0xba , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x02 , 0x00 , 0x00 , 0x00 , 0x2f , 0x55 , 0x73 , 0x65 , 0x72 , 0x73 , 0x2f , 0x6d , 0x73 , 0x61 , 0x6e , 0x66 , 0x74 , 0x2f , 0x2e , 0x63 , 0x61 , 0x72 , 0x67 , 0x6f , 0x2f , 0x72 , 0x65 , 0x67 , 0x69 , 0x73 , 0x74 , 0x72 , 0x79 , 0x2f , 0x73 , 0x72 , 0x63 , 0x2f , 0x69 , 0x6e , 0x64 , 0x65 , 0x78 , 0x2e , 0x63 , 0x72 , 0x61 , 0x74 , 0x65 , 0x73 , 0x2e , 0x69 , 0x6f , 0x2d , 0x36 , 0x66 , 0x31 , 0x37 , 0x64 , 0x32 , 0x32 , 0x62 , 0x62 , 0x61 , 0x31 , 0x35 , 0x30 , 0x30 , 0x31 , 0x66 , 0x2f , 0x63 , 0x69 , 0x70 , 0x68 , 0x65 , 0x72 , 0x2d , 0x30 , 0x2e , 0x34 , 0x2e , 0x34 , 0x2f , 0x73 , 0x72 , 0x63 , 0x2f , 0x73 , 0x74 , 0x72 , 0x65 , 0x61 , 0x6d , 0x2e , 0x72 , 0x73 , 0x00 , 0x00 , 0x00 , 0x9c , 0x01 , 0x10 , 0x00 , 0x5d , 0x00 , 0x00 , 0x00 , 0x78 , 0x00 , 0x00 , 0x00 , 0x27 , 0x00 , 0x00 , 0x00 , 0x66 , 0x6c , 0x61 , 0x67 , 0x5c , 0x7b , 0x28 , 0x5b , 0x5e , 0x7b , 0x7d , 0x5d , 0x2a , 0x29 , 0x5c , 0x7d , 0x73 , 0x72 , 0x63 , 0x2f , 0x6c , 0x69 , 0x62 , 0x2e , 0x72 , 0x73 , 0x00 , 0x00 , 0x1c , 0x02 , 0x10 , 0x00 , 0x0a , 0x00 , 0x00 , 0x00 , 0x18 , 0x00 , 0x00 , 0x00 , 0x2d , 0x00 , 0x00 , 0x00 , 0x6e , 0x61 , 0x68 , 0xf0 , 0x9f , 0x98 , 0x90 , 0xf0 , 0x9f , 0x98 , 0x90 , 0x79 , 0x61 , 0x73 , 0x73 , 0x73 , 0x21 , 0x21 , 0xf0 , 0x9f , 0x98 , 0x8c , 0xf0 , 0x9f , 0x92 , 0x85 , 0x00 , 0x00 , 0x03 , 0x00 , 0x00 , 0x00 , 0x0c , 0x00 , 0x00 , 0x00 , 0x04 , 0x00 , 0x00 , 0x00 , 0x04 , 0x00 , 0x00 , 0x00 , 0x1c , 0x02 , 0x10 , 0x00 , 0x0a , 0x00 , 0x00 , 0x00 , 0x15 , 0x00 , 0x00 , 0x00 , 0x2e , 0x00 , 0x00 , 0x00 , 0x43 , 0x6f , 0x75 , 0x6c , 0x64 , 0x6e , 0x27 , 0x74 , 0x20 , 0x63 , 0x6f , 0x70 , 0x79 , 0x20 , 0x62 , 0x75 , 0x66 , 0x66 , 0x65 , 0x72 , 0x20 , 0x63 , 0x6f , 0x6e , 0x74 , 0x65 , 0x6e , 0x74 , 0x73 , 0x00 , 0x00 , 0x00 , 0x74 , 0x02 , 0x10 , 0x00 , 0x1d , 0x00 , 0x00 , 0x00 , 0x2f , 0x55 , 0x73 , 0x65 , 0x72 , 0x73 , 0x2f , 0x6d , 0x73 , 0x61 , 0x6e , 0x66 , 0x74 , 0x2f , 0x44 , 0x6f , 0x63 , 0x75 , 0x6d , 0x65 , 0x6e , 0x74 , 0x73 , 0x2f , 0x44 , 0x6f , 0x63 , 0x75 , 0x6d , 0x65 , 0x6e , 0x74 , 0x73 , 0x20 , 0x2d , 0x20 , 0x4d , 0x6f , 0x72 , 0x69 , 0x74 , 0x7a , 0xe2 , 0x80 , 0x99 , 0x73 , 0x20 , 0x4d , 0x61 , 0x63 , 0x42 , 0x6f , 0x6f , 0x6b , 0x20 , 0x50 , 0x72 , 0x6f , 0x2f , 0x68 , 0x61 , 0x72 , 0x66 , 0x62 , 0x75 , 0x7a , 0x7a , 0x2d , 0x77 , 0x61 , 0x73 , 0x6d , 0x2d , 0x65 , 0x78 , 0x61 , 0x6d , 0x70 , 0x6c , 0x65 , 0x73 , 0x2f , 0x68 , 0x61 , 0x72 , 0x66 , 0x62 , 0x75 , 0x7a , 0x7a , 0x2d , 0x77 , 0x61 , 0x73 , 0x6d , 0x2f , 0x73 , 0x72 , 0x63 , 0x2f , 0x6c , 0x69 , 0x62 , 0x2e , 0x72 , 0x73 , 0x00 , 0x00 , 0x9c , 0x02 , 0x10 , 0x00 , 0x6a , 0x00 , 0x00 , 0x00 , 0x3e , 0x01 , 0x00 , 0x00 , 0x3b , 0x00 , 0x00 , 0x00 , 0x43 , 0x6f , 0x75 , 0x6c , 0x64 , 0x6e , 0x27 , 0x74 , 0x20 , 0x73 , 0x65 , 0x74 , 0x20 , 0x62 , 0x75 , 0x66 , 0x66 , 0x65 , 0x72 , 0x20 , 0x63 , 0x6f , 0x6e , 0x74 , 0x65 , 0x6e , 0x74 , 0x73 , 0x18 , 0x03 , 0x10 , 0x00 , 0x1c , 0x00 , 0x00 , 0x00 , 0x9c , 0x02 , 0x10 , 0x00 , 0x6a , 0x00 , 0x00 , 0x00 , 0x5e , 0x01 , 0x00 , 0x00 , 0x11 , 0x00 , 0x00 , 0x00 , 0x72 , 0x65 , 0x67 , 0x65 , 0x78 , 0x3a , 0x20 , 0x74 , 0x68 , 0x72 , 0x65 , 0x61 , 0x64 , 0x20 , 0x49 , 0x44 , 0x20 , 0x61 , 0x6c , 0x6c , 0x6f , 0x63 , 0x61 , 0x74 , 0x69 , 0x6f , 0x6e , 0x20 , 0x73 , 0x70 , 0x61 , 0x63 , 0x65 , 0x20 , 0x65 , 0x78 , 0x68 , 0x61 , 0x75 , 0x73 , 0x74 , 0x65 , 0x64 , 0x00 , 0x4c , 0x03 , 0x10 , 0x00 , 0x2b , 0x00 , 0x00 , 0x00 , 0x2f , 0x55 , 0x73 , 0x65 , 0x72 , 0x73 , 0x2f , 0x6d , 0x73 , 0x61 , 0x6e , 0x66 , 0x74 , 0x2f , 0x2e , 0x63 , 0x61 , 0x72 , 0x67 , 0x6f , 0x2f , 0x72 , 0x65 , 0x67 , 0x69 , 0x73 , 0x74 , 0x72 , 0x79 , 0x2f , 0x73 , 0x72 , 0x63 , 0x2f , 0x69 , 0x6e , 0x64 , 0x65 , 0x78 , 0x2e , 0x63 , 0x72 , 0x61 , 0x74 , 0x65 , 0x73 , 0x2e , 0x69 , 0x6f , 0x2d , 0x36 , 0x66 , 0x31 , 0x37 , 0x64 , 0x32 , 0x32 , 0x62 , 0x62 , 0x61 , 0x31 , 0x35 , 0x30 , 0x30 , 0x31 , 0x66 , 0x2f , 0x72 , 0x65 , 0x67 , 0x65 , 0x78 , 0x2d , 0x61 , 0x75 , 0x74 , 0x6f , 0x6d , 0x61 , 0x74 , 0x61 , 0x2d , 0x30 , 0x2e , 0x34 , 0x2e , 0x38 , 0x2f , 0x73 , 0x72 , 0x63 , 0x2f , 0x75 , 0x74 , 0x69 , 0x6c , 0x2f , 0x70 , 0x6f , 0x6f , 0x6c , 0x2e , 0x72 , 0x73 , 0x80 , 0x03 , 0x10 , 0x00 , 0x68 , 0x00 , 0x00 , 0x00 , 0x5e , 0x01 , 0x00 , 0x00 , 0x11 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x04 , 0x00 , 0x00 , 0x00 , 0x04 , 0x00 , 0x00 , 0x00 , 0x07 , 0x00 , 0x00 , 0x00 , 0x45 , 0x72 , 0x72 , 0x6f , 0x72 , 0x00 , 0x00 , 0x00 , 0x08 , 0x00 , 0x00 , 0x00 , 0x0c , 0x00 , 0x00 , 0x00 , 0x04 , 0x00 , 0x00 , 0x00 , 0x09 , 0x00 , 0x00 , 0x00 , 0x0a , 0x00 , 0x00 , 0x00 , 0x0b ] import re re_s = '104[8-9]\d\d\d' with open ( 'challenge.c' , 'r' ) as file : read_bytes = file .read() res = re.findall(re_s,read_bytes) start = 1048576 for r in res: address = int (r) address - = start if address > 1061 : continue temp = b'' for i in ss[address:address + 32 ]: # use 32 just want to see more temp + = i.to_bytes() print (temp,address + start) |
运行结果:
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 35 36 37 | python3. 11 parse.py b '/Users/msanft/.cargo/registry/sr' 1048576 b '/Users/msanft/.cargo/registry/sr' 1048576 b 't\x02\x10\x00\x1d\x00\x00\x00/Users/msanft/Documents/' 1049236 b "\x9c\x02\x10\x00j\x00\x00\x00>\x01\x00\x00;\x00\x00\x00Couldn't set buf" 1049352 b 'flag\\{([^{}]*)\\}src/lib.rs\x00\x00\x1c\x02\x10\x00' 1049100 b '\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x07\x00\x00\x00Error\x00\x00\x00\x08\x00\x00\x00\x0c\x00\x00\x00' 1049592 b '\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x07\x00\x00\x00Error\x00\x00\x00\x08\x00\x00\x00\x0c\x00\x00\x00' 1049592 b '/Users/msanft/.cargo/registry/sr' 1048712 b '/Users/msanft/.cargo/registry/sr' 1048576 b '/Users/msanft/.cargo/registry/sr' 1048576 b '\x08\x00\x00\x00\x0c\x00\x00\x00\x04\x00\x00\x00\t\x00\x00\x00\n\x00\x00\x00\x0b' 1049616 b '\x08\x00\x00\x00\x0c\x00\x00\x00\x04\x00\x00\x00\t\x00\x00\x00\n\x00\x00\x00\x0b' 1049616 b '\x00\x00\x10\x00h\x00\x00\x00=\x02\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00' 1048680 b 'called `Result::unwrap()` on an ' 1048900 b '\x03\x00\x00\x00\x0c\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x1c\x02\x10\x00\n\x00\x00\x00\x15\x00\x00\x00.\x00\x00\x00' 1049172 b "\x1c\x02\x10\x00\n\x00\x00\x00\x15\x00\x00\x00.\x00\x00\x00Couldn't copy bu" 1049188 b '\x88\x00\x10\x00h\x00\x00\x00^\x02\x00\x00\x1c\x00\x00\x00\x88\x00\x10\x00h\x00\x00\x00k\x02\x00\x002\x00\x00\x00' 1048816 b '\x88\x00\x10\x00h\x00\x00\x00k\x02\x00\x002\x00\x00\x00\x88\x00\x10\x00h\x00\x00\x00\x01\x03\x00\x00\x15\x00\x00\x00' 1048832 b '\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00/Users/msanft/.c' 1048696 b '\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00/Users/msanft/.c' 1048696 b '\x88\x00\x10\x00h\x00\x00\x00\x01\x03\x00\x00\x15\x00\x00\x00StreamCipherErro' 1048848 b '2-byte kcalled `Result::unwrap()' 1048892 b 'expand 32-byte kcalled `Result::' 1048884 b 'Mq\xac\x14v\xb1\x9al\xaa\xec\x86qA\x12\xf3\xbfkr\xf0\xa5kz\xfc\xd1\x1aR\x9c\xd3\xba\x00\x00\x00' 1048943 b 'yasss!!\xf0\x9f\x98\x8c\xf0\x9f\x92\x85\x00\x00\x03\x00\x00\x00\x0c\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00' 1049155 b 'nah\xf0\x9f\x98\x90\xf0\x9f\x98\x90yasss!!\xf0\x9f\x98\x8c\xf0\x9f\x92\x85\x00\x00\x03\x00\x00\x00' 1049144 b '\x18\x03\x10\x00\x1c\x00\x00\x00\x9c\x02\x10\x00j\x00\x00\x00^\x01\x00\x00\x11\x00\x00\x00regex: t' 1049396 b '\x9c\x02\x10\x00j\x00\x00\x00^\x01\x00\x00\x11\x00\x00\x00regex: thread ID' 1049404 b 'called `Result::unwrap()` on an ' 1048900 b '\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00/Users/msanft/.c' 1048972 b "\x9c\x01\x10\x00]\x00\x00\x00x\x00\x00\x00'\x00\x00\x00flag\\{([^{}]*)\\}" 1049084 b 'L\x03\x10\x00+\x00\x00\x00/Users/msanft/.cargo/reg' 1049464 b '\x80\x03\x10\x00h\x00\x00\x00^\x01\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x07\x00\x00\x00' 1049576 b 'StreamCipherError\x00\x00\x00expand 32-by' 1048864 b '\x08\x00\x00\x00\x0c\x00\x00\x00\x04\x00\x00\x00\t\x00\x00\x00\n\x00\x00\x00\x0b' 1049616 b 'Error\x00\x00\x00\x08\x00\x00\x00\x0c\x00\x00\x00\x04\x00\x00\x00\t\x00\x00\x00\n\x00\x00\x00\x0b' 1049608 |
这里为两个checker的结果输出字符串的引用
1 2 | b 'yasss!!\xf0\x9f\x98\x8c\xf0\x9f\x92\x85\x00\x00\x03\x00\x00\x00\x0c\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00' 1049155 b 'nah\xf0\x9f\x98\x90\xf0\x9f\x98\x90yasss!!\xf0\x9f\x98\x8c\xf0\x9f\x92\x85\x00\x00\x03\x00\x00\x00' 1049144 |
“expand 32-byte”为slasa20流密码家族中magic number
1 2 | b '2-byte kcalled `Result::unwrap()' 1048892 b 'expand 32-byte kcalled `Result::' 1048884 |
因为wasm程序不管怎么转化,始终都是‘汇编’的形式,又臭又长,所以我们的逆向还是要回归到这些汇编细节上,所以我们必须要了解这些算法在汇编层次上的不同
根据‘expand 32-byte k’我们知道了程序使用了salsa20家族中的某一个流密码算法
salsa20 流密码家族包括:
Xsalsa20 是Salsa20的改进,chacha20是Salsa20的变种,同理Xchacha20是在chacha20基础上的改进
初始矩阵为64字节的4*4的32bits数组,分为4个部分:
并且具体的分布也不同:
"expa" | Key | Key | Key |
---|---|---|---|
Key | "nd 3" | Nonce | Nonce |
Counter | Counter | "2-by" | Key |
Key | Key | Key | "te k" |
"expa" | "nd 3" | "2-by" | "te k" |
---|---|---|---|
Key | Key | Key | Key |
Key | Key | Key | Key |
Counter | Counter | Nonce | Nonce |
salsa20 与 chacha20都基于ARX,包括32 bit 的加法,异或,旋转
在代码上体现为QR()函数:
1 2 3 4 | b ^ = (a + d) <<< 7 ; c ^ = (b + a) <<< 9 ; d ^ = (c + b) <<< 13 ; a ^ = (d + c) <<< 18 ; |
1 2 3 4 | a + = b; d ^ = a; d <<< = 16 ; c + = d; b ^ = c; b <<< = 12 ; a + = b; d ^ = a; d <<< = 8 ; c + = d; b ^ = c; b <<< = 7 ; |
salsa20与chacha20都会进行20轮QR(),其中10轮偶数轮,10奇数轮
其中具体参与运算的块也不尽相同,具体如下:
salsa20:
1 2 3 4 5 6 7 8 9 10 | / / Odd round QR( 0 , 4 , 8 , 12 ) / / column 1 QR( 5 , 9 , 13 , 1 ) / / column 2 QR( 10 , 14 , 2 , 6 ) / / column 3 QR( 15 , 3 , 7 , 11 ) / / column 4 / / Even round QR( 0 , 1 , 2 , 3 ) / / row 1 QR( 5 , 6 , 7 , 4 ) / / row 2 QR( 10 , 11 , 8 , 9 ) / / row 3 QR( 15 , 12 , 13 , 14 ) / / row 4 |
chacha20:
1 2 3 4 5 6 7 8 9 10 | / / Odd round QR( 0 , 4 , 8 , 12 ) / / column 1 QR( 1 , 5 , 9 , 13 ) / / column 2 QR( 2 , 6 , 10 , 14 ) / / column 3 QR( 3 , 7 , 11 , 15 ) / / column 4 / / Even round QR( 0 , 5 , 10 , 15 ) / / diagonal 1 (main diagonal) QR( 1 , 6 , 11 , 12 ) / / diagonal 2 QR( 2 , 7 , 8 , 13 ) / / diagonal 3 QR( 3 , 4 , 9 , 14 ) / / diagonal 4 |
最后体现在代码上(C语言):
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 | //salsa20 #include <stdint.h> #define ROTL(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) #define QR(a, b, c, d)( \ b ^= ROTL(a + d, 7), \ c ^= ROTL(b + a, 9), \ d ^= ROTL(c + b,13), \ a ^= ROTL(d + c,18)) #define ROUNDS 20 void salsa20_block(uint32_t out[16], uint32_t const in[16]) { int i; uint32_t x[16]; for (i = 0; i < 16; ++i) x[i] = in[i]; // 10 loops × 2 rounds/loop = 20 rounds for (i = 0; i < ROUNDS; i += 2) { // Odd round QR(x[ 0], x[ 4], x[ 8], x[12]); // column 1 QR(x[ 5], x[ 9], x[13], x[ 1]); // column 2 QR(x[10], x[14], x[ 2], x[ 6]); // column 3 QR(x[15], x[ 3], x[ 7], x[11]); // column 4 // Even round QR(x[ 0], x[ 1], x[ 2], x[ 3]); // row 1 QR(x[ 5], x[ 6], x[ 7], x[ 4]); // row 2 QR(x[10], x[11], x[ 8], x[ 9]); // row 3 QR(x[15], x[12], x[13], x[14]); // row 4 } for (i = 0; i < 16; ++i) out[i] = x[i] + in[i]; } |
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 | //chacha20 #include<stdint.h>#define ROTL(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) #define QR(a, b, c, d) ( \ a += b, d ^= a, d = ROTL(d, 16), \ c += d, b ^= c, b = ROTL(b, 12), \ a += b, d ^= a, d = ROTL(d, 8), \ c += d, b ^= c, b = ROTL(b, 7)) #define ROUNDS 20 void chacha_block(uint32_t out[16], uint32_tconst in[16]) { int i; uint32_t x[16]; for (i = 0; i < 16; ++i) x[i] = in[i]; // 10 loops × 2 rounds/loop = 20 rounds for (i = 0; i < ROUNDS; i += 2) { // Odd round QR(x[0], x[4], x[ 8], x[12]); // column 1 QR(x[1], x[5], x[ 9], x[13]); // column 2 QR(x[2], x[6], x[10], x[14]); // column 3 QR(x[3], x[7], x[11], x[15]); // column 4 // Even round QR(x[0], x[5], x[10], x[15]); // diagonal 1 (main diagonal) QR(x[1], x[6], x[11], x[12]); // diagonal 2 QR(x[2], x[7], x[ 8], x[13]); // diagonal 3 QR(x[3], x[4], x[ 9], x[14]); // diagonal 4 } for (i = 0; i < 16; ++i) out[i] = x[i] + in[i]; } |
具体参考了这篇论文:https://cr.yp.to/snuffle/xsalsa-20110204.pdf
初始状态矩阵不同:
初始状态矩阵x:
0 | 1 | 2 | 3 |
---|---|---|---|
4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 |
Xslasa20在slasa20的基础上使用192bit的nonce,其中x6,x7,x8,x9为nonce,其他与slasa20相同
你可能注意到counter部分消失了,流密码没有counter怎么能行,其实这部分在Hslasa20实现了:
HSlasa20是XSalsa20独有的部分,并在Xsalsa20中首先运行,来产生额外的64bits nonce和64bits counter
Hslasa20根据Xslasa20的初始矩阵,产生256 bits的数据(z0,z1,...,z15)
为什么是256bits
因为根据安全考虑,hslasa20会任意的丢弃一般的256bits,相关细节请参考上面的论文。
如在论文的例子里丢弃了(z0,z5,z10,z15,z6,z7,z8,z9).
Xslasa20随后根据(z0,z1,...,z15) 补充额外的64bits nonce和64bits counter(摘抄自论文):
随后便是和slasa20一样的流程。
看slasa20与chacha20,就看初始矩阵‘expend 32-byte k’是对角线填充还是一行填充
看slasa20与Xslasa20,chacha20与Xchacha20,就看初始矩阵nonce的填充长度
定位constants填充的位置:
1 2 | b '2-byte kcalled `Result::unwrap()' 1048892 b 'expand 32-byte kcalled `Result::' 1048884 |
前8字节
1 2 3 4 5 | var_i0 = var_p3; var_i1 = 1048884u; var_j1 = i64_load(&instance->w2c_memory, (u64)(var_i1)); var_l808 = var_j1; i64_store(&instance->w2c_memory, (u64)(var_i0) + 288, var_j1); |
后8字节
1 2 3 4 5 6 7 8 9 | var_i0 = 0u; var_p2 = var_i0; var_i0 = var_p3; var_i1 = 296u; var_i0 += var_i1; var_i1 = 1048892u; var_j1 = i64_load(&instance->w2c_memory, (u64)(var_i1)); var_l808 = var_j1; i64_store(&instance->w2c_memory, (u64)(var_i0), var_j1); |
计算前后8字节的位置的距离:296-288 = 8。可以发现地址是连续的8字节,这说明是按行填充,那么使用的算法是chacha20.
当然在wasm2wat转化的dcmp文件中也可以找到chacha20.rs的信息,但是藏在巨量的字符串里,只能尝试搜索试一试,或者做一个验证也可
如法炮仗,找到key填充的部分,按照8字节填充规律,key为32字节,需填充四次,地址应为304,
312,320,328。果然找到了key的填充部分:
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 | var_i0 = var_p3; var_i0 = i32_load(&instance->w2c_memory, (u64)(var_i0) + 4u); var_p0 = var_i0; var_i0 = var_p3; var_i0 = i32_load(&instance->w2c_memory, (u64)(var_i0)); var_p4 = var_i0; var_i0 = var_p3; var_i1 = 304u; var_i0 += var_i1; var_j1 = 1374463283923456787ull; i64_store(&instance->w2c_memory, (u64)(var_i0), var_j1); var_i0 = var_p3; var_i1 = 312u; var_i0 += var_i1; var_j1 = 1374463283923456787ull; i64_store(&instance->w2c_memory, (u64)(var_i0), var_j1); var_i0 = var_p3; var_i1 = 320u; var_i0 += var_i1; var_j1 = 1374463283923456787ull; i64_store(&instance->w2c_memory, (u64)(var_i0), var_j1); var_i0 = var_p3; var_i1 = 328u; var_i0 += var_i1; var_j1 = 1374463283923456787ull; i64_store(&instance->w2c_memory, (u64)(var_i0), var_j1); |
hex(1374463283923456787) = ‘0x13’ * 8 key即为‘0x13’ * 32
如法炮制 找到nonce的位置
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 35 36 37 38 39 | vvar_i0 = var_p3; var_i1 = 128u; var_i0 += var_i1; var_p1 = var_i0; var_i1 = 926365495u; // 0x37373737 last 4bytes nonce i32_store(&instance->w2c_memory, (u64)(var_i0), var_i1); var_i0 = var_p3; var_i1 = 160u; var_i0 += var_i1; var_j1 = var_l808; i64_store(&instance->w2c_memory, (u64)(var_i0), var_j1); var_i0 = var_p3; var_i1 = 168u; var_i0 += var_i1; var_j1 = 1374463283923456787ull; i64_store(&instance->w2c_memory, (u64)(var_i0), var_j1); // maybe matrix copy var_i0 = var_p3; var_i1 = 176u; var_i0 += var_i1; var_j1 = 1374463283923456787ull; i64_store(&instance->w2c_memory, (u64)(var_i0), var_j1); var_i0 = var_p3; var_i1 = 184u; var_i0 += var_i1; var_j1 = 1374463283923456787ull; i64_store(&instance->w2c_memory, (u64)(var_i0), var_j1); var_i0 = var_p3; var_i1 = 192u; var_i0 += var_i1; var_j1 = 1374463283923456787ull; i64_store(&instance->w2c_memory, (u64)(var_i0), var_j1); var_i0 = var_p3; var_i1 = 1048884u; var_j1 = i64_load(&instance->w2c_memory, (u64)(var_i1)); var_l808 = var_j1; i64_store(&instance->w2c_memory, (u64)(var_i0) + 288, var_j1); var_i0 = var_p3; var_j1 = 3978709506094217015ull; //0x3737373737373737 first 8bytes nonce i64_store(&instance->w2c_memory, (u64)(var_i0) + 120, var_j1); |
nonce 为 ‘0x37’ * 12
密文定位:
1 | b 'Mq\xac\x14v\xb1\x9al\xaa\xec\x86qA\x12\xf3\xbfkr\xf0\xa5kz\xfc\xd1\x1aR\x9c\xd3\xba\x00\x00\x00' 1048943 |
该引用十分可疑 起出现在yasss!!!和nah前面 密文的可能性很高
尝试解密:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | from Crypto.Cipher import ChaCha20 from Crypto.Random import get_random_bytes def chacha20_decrypt(key, nonce, ciphertext): cipher = ChaCha20.new(key = key, nonce = nonce) plaintext = cipher.decrypt(ciphertext) return plaintext key = b '\x13' * 32 nonce = b '\x37' * 12 ciphertext = b "Mq\xac\x14v\xb1\x9al\xaa\xec\x86qA\x12\xf3\xbfkr\xf0\xa5kz\xfc\xd1\x1aR\x9c\xd3\xba" decrypted_text = chacha20_decrypt(key, nonce, ciphertext) print ( "Decrypted text:" , decrypted_text) #Decrypted text: b'H4rfBuzZ_g0t_m3_1n70_5h4P3_!!' |
放入前面提到的程序中,验证成功,此题得解!
先说题目,这是一道创新性极高,难度极高,同时趣味性极高的题目。首先是ttf文件,里面竟然可以暗藏wasm,通过调研这是harfbuzz的wasm shaper,在harfbuzz-wasm-examples学习到tff文件也可以变着花样甚至可以实现一个计算器,在本题中除了是一个正常的字体以外,竟然还是一个flag checker,对所有符合flag{}正则的字符串,输出正误结果,真是太妙了。
再说我的做题过程,大部分时间花在了如何想法让wasm好分析,最后折腾下来还是老老实实的分析又臭又长的跟汇编没区别的c语言,但是在这个过程,我总结出逆向wasm的一个方法:
寻找对关键关键缓冲区的引用,来寻找关键逻辑的蛛丝马迹。因为通过其他语言编译成wasm,表现在wasm中总是在关键逻辑上加上大量的看似无关的代码,人工分析工作量太大
什么是关键是关键缓冲区?
我理解为和程序逻辑相关的缓冲区,这里一般为通过wasm2*出来文件中的第一个缓冲区(经验)。通过我自己实验,通过wasm-pack把rust编译成wasm,事实也是如此。
关键函数
#[wasm_bindgen]
的attribute,实现这个attribute的目的就是让这个函数导出让wasm调用到。在解这道题的时候我也试着自己写一个rust程序编译成wasm,然后反编译出来找找异同点,来给这道题找思路
我的核心lib.rs:
1 2 3 4 5 6 7 8 9 10 11 | use wasm_bindgen::prelude::*; #[wasm_bindgen] extern { pub fn alert(s: &str); } #[wasm_bindgen(start)] pub fn greet() { alert(&format!( "Hello, {}!" , "123" )); } |
可以看到这里我和官方教程所不同的是 我对greet函数的实现了#[wasm_bindgen(start)]
而不是
#[wasm_bindgen]
。加了start可以起到什么作用?
在生成的wasm文件中可以看到__wbindgen_start()中除了默认的call __wbindgen_init_externref_table() , 还增加了 call greet()
编写html调用它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <!doctype html> < html lang = "en-US" > < head > < meta charset = "utf-8" /> < title >hello-wasm example</ title > </ head > < body > < script type = "module" > import init, { greet } from "./pkg/hello_wasm.js"; init().then(() => { // greet("WebAssembly"); }); </ script > </ body > </ html > |
python起一个http,浏览器访问:
发现直接就调用了greet()
跟进init()发现调用了 __wbg_init()
async function __wbg_init(module_or_path) { if (wasm !== undefined) return wasm; if (typeof module_or_path !== 'undefined') { if (Object.getPrototypeOf(module_or_path) === Object.prototype) { ({module_or_path} = module_or_path) } else { console.warn('using deprecated parameters for the initialization function; pass a single object instead') } } if (typeof module_or_path === 'undefined') { module_or_path = new URL('hello_wasm_bg.wasm', import.meta.url); } const imports = __wbg_get_imports(); if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) { module_or_path = fetch(module_or_path); } __wbg_init_memory(imports); const { instance, module } = await __wbg_load(await module_or_path, imports); return __wbg_finalize_init(instance, module); }
__wbg_init()在最后调用了_wbg_finalize_init()
function __wbg_finalize_init(instance, module) { wasm = instance.exports; __wbg_init.__wbindgen_wasm_module = module; cachedUint8ArrayMemory0 = null; wasm.__wbindgen_start(); return wasm; }
可以发现__wbg_finalize_init()调用了__wbindgen_start(),而__wbindgen_start()将调用到我们greet(),最后返回完成初始化。这就跟c语言中的init_array一样。
那么在这里我们可以通过这个功能实现一些hook,反调试,加密,解密,混淆等等,哈哈哈。
更多【CTF对抗-hack.lu 2024 Getting into Shape wp】相关视频教程:www.yxfzedu.com