CTF 丛林的秘密:算法分析

WriteUp 3周前 admin
18 0 0




背景


这一题很有迷惑性,设置了很多陷阱,看似正常的逻辑其实是假象。里面用到了Webassembly逆向,我也是第一次遇到这种,之前没有触过wasm汇编语言,看到代码也是无从下手,也是一边学习一边算法逆向。





代码分析


java层分析

从代码可以看出满足native int check_key(String str) 为真时候,则验证通过,同时也调用了sayHello(),调用的具体作用还看不出来。


CTF 丛林的秘密:算法分析


so层分析

从导出函数列表中,找到我们的目标函数:


CTF 丛林的秘密:算法分析


Java_com_example_assemgogogo_gogogoJNI_sayHello

这段代码的意思就是返回字符串:http://127.0.0.1:8000


CTF 丛林的秘密:算法分析


Java_com_example_assemgogogo_gogogoJNI_check_key

CTF 丛林的秘密:算法分析

主要步骤如下:通过 JNI 调用 Java 中的方法(通过函数指针调用),返回结果存储在 result 变量中。


如果调用成功,进入密钥检查的逻辑。


使用 srand(0x32u) 设置随机数生成器的种子。


在循环中,生成随机数 v8,然后根据一些条件检查当前密钥字节是否符合预期。
如果所有密钥字节都通过检查,返回 0;否则,关闭套接字并返回 1。


v8是一个随机数,if ( *(_BYTE *)(v6 + v7) != (v8 – (v9 & 0xFFFFFF80) != (unsigned __int8)aD584a68d4e213d[v7]) )


结果肯定是不相等的,那么通过分析返回值永远都是0,那么不成立,这个函数岂不是无解?





hook验证


既然通过代码分析,我们知道他们调用了_check_key、sayHello这个2个函数,那么我们就hook他们,验证下。


function hook_jiami() {
Java.perform(function () {
var gogogoJNI = Java.use("com.example.assemgogogo.gogogoJNI");
gogogoJNI["sayHello"].implementation = function () {
console.log("gogogoJNI.sayHello is called");
var result = this["sayHello"]();
console.log("gogogoJNI.sayHello result=${result}", result);
return result;
};
gogogoJNI["check_key"].implementation = function (str) {
console.log("gogogoJNI.check_key is called: str=${str}", str);
var result = this["check_key"](str);
console.log("gogogoJNI.check_key result=${result}", result);
return result;
};
});
}

CTF 丛林的秘密:算法分析


通过结果可以看出,只调用了sayHello函数并没有调用check_key函数,结合之前的分析可以得出,此处并非是真正的位置,check_key函数又在哪调用的呢?

再来看java层代码中:
((WebView) findViewById(R.id.text1View)).loadUrl(this.u);
((WebView) findViewById(R.id.text1View)).getSettings().setJavaScriptEnabled(true);
this.u = :http://127.0.0.1:8000setJavaScriptEnabled 启用了JavaScript。


接着分析:在so文件JNI_OnLoad中调用了inti_proc函数:


CTF 丛林的秘密:算法分析


使用一个循环,将一系列向量进行初始化,涉及到按位异或操作。


使用一系列操作配置了套接字相关的参数,包括套接字类型、协议等。


通过 getaddrinfo 获取了本地主机(IP地址为0)在端口8000上的地址信息,并将结果存储在 v19 中。


在获取的地址信息上循环,尝试创建套接字并设置一些选项。


套接字创建和配置成功,创建了多个线程。


返回值 nullsub_:


CTF 丛林的秘密:算法分析

mm0 是关键,我们hook之:


function hook_jiami() {
Java.perform(function () {
var module_addr = Module.findBaseAddress("libgogogo.so");
var mm0__addr = Module.findExportByName("libgogogo.so","mm0");

console.log("module_addr = ", module_addr);

var get_html = mm0__addr.readByteArray(35000);

console.log("mm0__addr_addr 3333 ",get_html)
});
}

CTF 丛林的秘密:算法分析

得到一串代码,可以看出他是一个html页面,看来交互就是和他进行了。我们在弄出完整的html页面看看:


function bytesToString(arr) {
if (typeof arr === 'string') {
return arr;
}
var str = "";
arr = new Uint8Array(arr);
for (var i in arr) {
str += String.fromCharCode(arr[i]);
}
return str
}

function hook_jiami() {
Java.perform(function () {
var module_addr = Module.findBaseAddress("libgogogo.so");
var mm0__addr = Module.findExportByName("libgogogo.so","mm0");
console.log("module_addr = ", module_addr);
var get_html = mm0__addr.readByteArray(35000);
var get_html1 = bytesToString(get_html);
console.log("nmm0__addr_addr 4444 ",bytesToString(get_html))

});
}

CTF 丛林的秘密:算法分析


<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<style>
body {
background-color: rgb(255, 255, 255);
}
</style>
</head>
<script>


var instance;

WebAssembly.compile(new Uint8Array(`
00 61 73 6D 01 00 00 00 01 1B 05 60 00 00 60 04
7F 7F 7F 7F 01 7F 60 02 7F 7F 01 7F 60 01 7F 01
7F 60 00 01 7F 03 0E 0D 00 01 01 01 01 01 01 01
01 02 03 04 04 04 05 01 70 01 01 01 05 03 01 00
02 06 15 03 7F 01 41 D0 89 04 0B 7F 00 41 D0 89

...

00 00 00 83 01 04 6E 61 6D 65 01 7C 0D 00 11 5F
5F 77 61 73 6D 5F 63 61 6C 6C 5F 63 74 6F 72 73
01 01 6F 02 02 6F 6F 03 03 6F 6F 6F 04 04 6F 6F
6F 6F 05 05 6F 6F 6F 6F 6F 06 06 6F 6F 6F 6F 6F
6F 07 07 6F 6F 6F 6F 6F 6F 6F 08 08 6F 6F 6F 6F
6F 6F 6F 6F 09 0E 73 65 74 5F 69 6E 70 75 74 5F
66 6C 61 67 0A 12 73 65 74 5F 69 6E 70 75 74 5F
66 6C 61 67 5F 6C 65 6E 0B 09 63 68 65 63 6B 5F
6B 65 79 0C 03 78 78 78
`
.trim().split(/[srn]+/g).map(str => parseInt(str, 16))
)).then(module => {
new WebAssembly.instantiate(module).then(results => {
instance = results;
}).catch(console.error);})
function check_flag(){
var value = document.getElementById("key_value").value;
if(value.length != 32)
{
document.getElementById("tips").innerHTML = "Not Correct!";
return;
}
instance.exports.set_input_flag_len(value.length);
for(var ii=0;ii<value.length;ii++){
instance.exports.set_input_flag(value[ii].charCodeAt(),ii);
}
var ret = instance.exports.check_key();

if (ret == 1){
document.getElementById("tips").innerHTML = "Congratulations!"
}
else{
document.getElementById("tips").innerHTML = "Not Correct!"
}
}
</script>
<body>
<div>Key: <input id="key_value" type="text" name="key" style="width:60%" ;="" value=""> <input type="submit" value="check" onclick="check_flag()"></div>
<div> <label id="tips"></label></div>

</body></html>





WebAssembly基本概念


WebAssembly(简称为Wasm)是一种面向Web的二进制指令格式。它是一种可移植、高性能的虚拟机,旨在在Web浏览器中执行底层代码,以提供接近本地代码执行速度的性能。


以下是关于WebAssembly的基本概念。


二进制指令格式:

WebAssembly使用紧凑的二进制格式,可以更高效地传输和解码,同时减小加载时间。这使得WebAssembly成为Web平台上的一个通用执行格式。


独立于编程语言:

WebAssembly并不依赖于特定的编程语言,而是设计为与多种语言兼容。它可以被用作JavaScript之外的语言的目标,使得开发者可以使用各种语言编写Web应用的核心功能。


执行环境:

WebAssembly代码在浏览器中执行,但它不直接在JavaScript引擎上运行。相反,WebAssembly有自己的虚拟机,与浏览器的JavaScript引擎分开。这使得WebAssembly能够获得与本地代码相媲美的性能。


跨平台:

WebAssembly是一个跨平台的技术,可以在不同体系结构和操作系统上运行。这使得开发者可以编写一次代码,并在各种设备和环境中部署,而无需修改。


安全性:

WebAssembly被设计为在Web环境中运行,同时具有强大的安全性。它在一个受控的沙箱中运行,防止对计算机系统的恶意访问。此外,WebAssembly模块可以通过浏览器的同源策略限制来提高安全性。


JavaScript和WebAssembly的互操作性:

WebAssembly与JavaScript有良好的互操作性。JavaScript可以调用WebAssembly的函数,而WebAssembly也可以调用JavaScript的函数,使得两者可以共同工作。


使用场景:

WebAssembly广泛应用于需要高性能的Web应用程序,例如图形、游戏、模拟器、数据处理等。它允许开发者在Web上执行密集型计算任务,而不会损失性能。

工具链支持:

WebAssembly有完整的工具链,包括编译器和调试器,使得开发者能够方便地将其集成到现有的开发工作流程中。





处理wasm文件


从github下载工具,对文件进行反编译https://github.com/WebAssembly/wabt:


./wasm2c /root/Desktop/hex.wasm -o web.c


此时代码看上去是又多又长,分析起来比较吃力。gcc编译web.c获得中间文件web.o:


gcc -c web.c -o web.o


将web.o拖到IDA中分析。


w2c_check_key()就是核心代码了:


CTF 丛林的秘密:算法分析


w2c_o内部逻辑都是一样的:


CTF 丛林的秘密:算法分析


函数签名:
函数名为 w2c_o。


返回一个64位整数 __int64,使用 __fastcall 调用约定,表明一些参数可能会通过寄存器传递。接受四个无符号整数参数 a1、a2、a3、a4。


局部变量和参数:
使用了一系列整数变量,如 v4、v5、v6、…、v28。v26、v17、v16、v15、v23、v21 等变量在后续的运算中被使用。


内存操作:
使用 i32_load8_u 和 i32_load8_s 从内存中加载8位整数。使用 i32_store8 将8位整数写入内存。


逻辑运算和条件判断:
对变量进行递增、逻辑与、逻辑或等操作,生成一系列的逻辑条件。根据条件判断执行不同的逻辑分支。


循环:
使用 do-while 循环,在循环体内执行一系列的操作。


返回值:
最终返回一个64位整数 v18。


调用 wasm_rt_trap 函数:
在代码开头,使用 wasm_rt_call_stack_depth 变量判断调用深度,如果超过一定深度,就会调用 wasm_rt_trap 函数,并传递参数7。


数据处理和异或运算:
对参数进行一系列复杂的逻辑运算,包括位异或运算,与运算,或运算等。

条件判断:
根据条件的不同执行不同的逻辑分支。


最后的返回:
根据条件计算得到的最终结果 v18 作为函数的返回值。

w2c_xxx() 是一个32元方程组:


CTF 丛林的秘密:算法分析


import numpy as np
from scipy.linalg import solve
a = np.array(
[[108, 111, 92, 194, 124, 240, 126, 81, 144, 103, 161, 50, 67, 15, 127, 232, 188, 19, 233, 153, 231, 40, 112, 106,
135, 90, 67, 20, 248, 45, 48, 174],
[227, 78, 195, 81, 10, 248, 186, 171, 148, 194, 40, 180, 17, 212, 104, 90, 178, 26, 225, 209, 32, 169, 94, 156,
154, 56, 244, 149, 120, 131, 13, 101],
[83, 44, 95, 131, 30, 55, 46, 36, 67, 109, 69, 251, 8, 248, 40, 154, 251, 86, 112, 9, 174, 197, 38, 14, 202, 60,
117, 188, 136, 145, 240, 53],
[152, 162, 112, 57, 102, 182, 10, 139, 30, 7, 145, 127, 148, 5, 165, 109, 110, 234, 113, 33, 192, 45, 65, 105, 140,
116, 35, 48, 155, 25, 234, 25],
[101, 189, 236, 118, 141, 148, 197, 7, 108, 104, 45, 130, 39, 164, 88, 241, 108, 107, 76, 34, 210, 29, 156, 90,
139, 151, 10, 97, 209, 46, 82, 113],
[182, 13, 50, 102, 155, 230, 3, 225, 237, 163, 38, 176, 115, 105, 203, 26, 72, 111, 96, 240, 139, 117, 153, 120,
151, 25, 49, 90, 98, 7, 179, 72],
[170, 150, 226, 101, 110, 99, 127, 101, 203, 209, 187, 100, 226, 186, 252, 39, 65, 67, 225, 174, 1, 187, 214, 22,
74, 99, 129, 254, 13, 97, 156, 61],
[1, 88, 118, 232, 60, 252, 133, 177, 185, 222, 32, 48, 1, 242, 240, 218, 81, 22, 73, 171, 139, 72, 106, 62, 156,
134, 220, 19, 77, 94, 154, 117],
[189, 173, 41, 39, 26, 232, 75, 75, 95, 7, 117, 96, 211, 130, 228, 143, 91, 247, 43, 122, 131, 52, 48, 29, 111, 38,
19, 242, 162, 70, 220, 151],
[236, 136, 147, 104, 79, 204, 220, 25, 38, 233, 165, 20, 174, 120, 214, 18, 233, 119, 244, 143, 126, 226, 77, 33,
189, 5, 150, 160, 14, 112, 231, 92],
[191, 38, 193, 250, 212, 175, 39, 94, 183, 172, 171, 163, 129, 165, 64, 170, 199, 2, 167, 2, 216, 252, 184, 187,
97, 109, 98, 135, 192, 88, 50, 203],
[203, 81, 252, 104, 248, 156, 199, 46, 208, 240, 149, 155, 102, 95, 51, 208, 208, 62, 58, 117, 72, 23, 193, 193,
226, 217, 106, 147, 136, 16, 43, 196],
[144, 69, 224, 107, 225, 83, 15, 10, 214, 152, 24, 136, 165, 208, 38, 67, 201, 180, 158, 75, 111, 65, 211, 220,
135, 125, 216, 105, 122, 112, 80, 49],
[143, 68, 127, 51, 152, 88, 153, 9, 149, 107, 178, 166, 190, 177, 99, 71, 63, 233, 58, 132, 109, 75, 152, 95, 74,
195, 90, 251, 205, 8, 76, 129],
[209, 146, 59, 38, 40, 56, 182, 245, 67, 202, 177, 183, 26, 126, 161, 95, 133, 123, 163, 30, 88, 219, 5, 86, 183,
156, 253, 97, 43, 128, 31, 102],
[146, 223, 137, 228, 226, 155, 170, 92, 77, 17, 22, 128, 20, 171, 142, 170, 192, 49, 200, 178, 154, 42, 5, 159,
251, 152, 7, 247, 145, 39, 91, 136],
[169, 204, 244, 26, 77, 134, 221, 205, 149, 47, 1, 197, 82, 195, 123, 219, 116, 80, 13, 231, 173, 192, 220, 224,
108, 104, 56, 152, 84, 226, 121, 205],
[184, 45, 176, 126, 118, 161, 142, 171, 215, 83, 233, 184, 171, 182, 126, 111, 118, 67, 92, 219, 70, 252, 194, 21,
245, 204, 48, 150, 39, 85, 73, 95],
[48, 224, 164, 138, 92, 3, 191, 94, 19, 50, 34, 167, 75, 72, 238, 15, 111, 216, 84, 40, 145, 112, 140, 204, 154,
195, 175, 250, 202, 169, 170, 120],
[112, 19, 189, 50, 247, 240, 164, 5, 139, 56, 19, 4, 23, 172, 96, 254, 63, 247, 149, 183, 128, 147, 213, 243, 172,
144, 246, 25, 106, 176, 170, 68],
[184, 22, 183, 128, 149, 174, 227, 113, 65, 159, 74, 170, 186, 174, 211, 1, 223, 156, 253, 223, 241, 252, 148, 93,
41, 125, 27, 136, 78, 248, 41, 31],
[155, 237, 242, 10, 145, 99, 239, 105, 3, 43, 46, 155, 208, 75, 140, 181, 197, 140, 10, 170, 142, 212, 186, 27,
105, 118, 198, 243, 13, 113, 82, 39],
[207, 206, 127, 58, 91, 87, 7, 17, 63, 180, 40, 96, 202, 185, 68, 72, 240, 36, 139, 199, 76, 229, 159, 136, 94, 19,
3, 87, 45, 6, 136, 50],
[115, 215, 40, 166, 87, 83, 74, 202, 235, 149, 114, 76, 204, 218, 63, 123, 9, 172, 38, 138, 35, 200, 221, 144, 235,
108, 1, 245, 153, 184, 90, 12],
[123, 190, 55, 180, 84, 231, 81, 116, 61, 3, 94, 85, 190, 187, 142, 62, 225, 240, 179, 150, 77, 85, 196, 12, 144,
122, 28, 224, 248, 143, 114, 36],
[2, 202, 40, 224, 154, 65, 30, 241, 13, 213, 176, 122, 30, 158, 14, 191, 80, 116, 74, 70, 32, 189, 76, 95, 158,
103, 7, 201, 204, 91, 190, 122],
[42, 154, 223, 165, 155, 101, 75, 95, 253, 14, 158, 199, 110, 89, 205, 202, 83, 162, 67, 30, 115, 83, 27, 31, 118,
160, 248, 66, 88, 44, 5, 176],
[34, 168, 72, 160, 243, 41, 146, 29, 62, 235, 185, 180, 10, 150, 208, 140, 125, 114, 35, 34, 38, 123, 163, 208, 5,
29, 207, 111, 72, 65, 125, 84],
[18, 11, 26, 175, 44, 128, 32, 100, 21, 116, 253, 213, 67, 16, 171, 178, 97, 7, 162, 152, 78, 167, 177, 97, 26,
155, 127, 21, 243, 188, 140, 197],
[140, 110, 164, 208, 72, 113, 9, 47, 179, 166, 51, 34, 91, 184, 89, 162, 233, 127, 156, 127, 244, 183, 193, 138,
242, 90, 193, 7, 252, 113, 152, 7],
[133, 105, 75, 146, 173, 27, 97, 142, 164, 15, 10, 177, 239, 141, 189, 67, 153, 108, 206, 210, 171, 252, 84, 249,
7, 168, 100, 30, 196, 244, 197, 75],
[147, 221, 57, 186, 69, 230, 167, 3, 220, 63, 218, 235, 156, 146, 75, 198, 204, 197, 59, 61, 179, 47, 221, 127,
210, 218, 241, 135, 196, 185, 53, 79],
]
)
b = np.array([359512,387514,301487,296549,344514,346892,386678,348667,316884,372620,413102,428661,371484,350848,334408,382822,420160,402263,366968,384909,425203,372162,297509,372215,370337,314564,325974,307088,322340,380716,393331,430295])
x = solve(a, b)
print(x)

CTF 丛林的秘密:算法分析

对相应位进行异或:


ss = "S0m3time_l1tt1e_c0de_1s_us3ful33"

yh=[0x18,9,3,0x6b,1,0x5a,0x32,0x57,0x30,0x5d,0x40,0x46,0x2b,0x46,0x56,0x3d,2,0x43,0x17,0,0x32,0x53,0x1f,0x26,0x2a,1,0,0x10,0x10,0x1e,0x40,0]
temp=[]
for i in range(32):
x=ord(ss[i])^yh[i]
temp.append(chr(x))
print(''.join(temp))
# 得到结果:K9nXu3_2o1q2_w3bassembly_r3vers3



CTF 丛林的秘密:算法分析


看雪ID:西贝巴巴

https://bbs.kanxue.com/user-home-961239.htm

*本文为看雪论坛优秀文章,由 西贝巴巴 原创,转载请注明来自看雪社区

CTF 丛林的秘密:算法分析


# 往期推荐

1、区块链智能合约逆向-合约创建-调用执行流程分析

2、在Windows平台使用VS2022的MSVC编译LLVM16

3、神挡杀神——揭开世界第一手游保护nProtect的神秘面纱

4、为什么在ASLR机制下DLL文件在不同进程中加载的基址相同

5、2022QWB final RDP

6、华为杯研究生国赛 adv_lua


CTF 丛林的秘密:算法分析

CTF 丛林的秘密:算法分析

球分享

CTF 丛林的秘密:算法分析

球点赞

CTF 丛林的秘密:算法分析

球在看


CTF 丛林的秘密:算法分析

点击阅读原文查看更多

原文始发于微信公众号(看雪学苑):CTF 丛林的秘密:算法分析

版权声明:admin 发表于 2024年2月7日 下午6:00。
转载请注明:CTF 丛林的秘密:算法分析 | CTF导航

相关文章