牛蛙资源网 - 只为资源而生,分享永无止境
牛蛙资源网-只为资源而生,分享永无止境,牛蛙网

穿堂风真的影响家人的健康吗(长头发真的影响智力吗)

牛蛙小编 交流杂谈

多元方程是什么意思,长头发真的影响学习吗

今天周五了,不知道大家想看点什么,Tiger就更新一个CTF的多元线性方程吧,前阵子HW闹的好多话不敢说,下周正常恢复更新,如果各位亲爱的粉丝们有哪方面想看的文章或者问题,可以在下方留言告诉Tiger或者去咱官网查看www.edusahoo.com免费的课程。

今天更两篇,祝大家看的舒服~手机不卡机~

概述

本片分析文章通过一道看雪CTF题讲述作者的整个分析流程,学习WebAssemble,Z3库,IDC脚本,多元线性方程等内容

分析流程

安装应用后,出现一个输入框和一个按钮

安卓

jadx反编译的apk后先查看清单清单文件的注册组件,只有一个入 *** 动类,进入查看

初现迷雾

之一眼:看到Congratulations,我们的目标是打印出这里的字符串,也就是点击按钮后调用本地 *** check_key返回值为1即可

再仔细看看:这里有个网页视图组件,这个组件表示有访问 *** 的操作,但是手机界面并没有看页面,我们去布局文件中看看,只需我们要看一个属性android:visibility表示控件是否可见,只有WebView中可见,按钮,输入框什么的都是隐藏的,并且这个网页流量占据的整个界面,所以我们看到的输入框和按钮都是网页展示的,所以我们需要关注的点就是sayHello的这个本地 *** ,它传入的网址是哪里的,这是我们下一步的要干的事

public String u = gogogoJNI 。sayHello () 静态的 { 系统。loadLibrary (gogogo ) } protected void onCreate (Bundle bundle ) { super 。onCreate (捆绑) 的setContentView ((INT ) - [R 。布局。activity_main ) 这个。eText1 = (的EditText ) findViewById (? 。ID 。EDITTEXT ) 这个。txView1 = (TextView的) findViewById (? 。ID。textView ) ((web视图) findViewById (? 。ID 。text1View ))。使用loadURL (此。? ) ((web视图) findViewById (? 。ID 。text1View ))。getSettings ()。setJavaScriptEnabled (true ) 这个。按钮1 = (按钮) findViewById (? 。ID 。按钮) 这个。button1 。setOnClickListener (新 OnClickListener () { 公共 无效 的onClick (查看 视图) { 如果 (gogogoJNI 。check_key (MainActivity 。这个。eText1 。gettext的()。的toString ()) == 1 ) { MainActivity 。这个。txView1 。的setText (恭喜! ) } else { MainActivity 。这个。txView1 。setText (Not Correct! ) } } }

探索网址

打开LIB文件夹,出现四个ABI架构对应的那么文件,基本现在手机的芯片都是支持的,这里ARM64在ida6.8不能使用F5大法,所以我们就分析armeabi-V7这个就行了

我们可以看看之一步我们排除的check_key *** ,这里逻辑是输出的32位数都为1即可返回1,实际尝试是错误的,混淆视听

在导出表中找到SayHello的 *** ,要使用F5大法先右键将这个区域代码创建为函数。接着讲这个字节数组异或计算即可的到URL地址。下面写了一个简短的IDC脚本获取到URL地址为http://127.0.0.1:8000

分析到这里,虽然我们探索网址已经完成,但是却没有看见服务端处理的函数,这个才是我们访问URL的时候,处理我们访问请求的函数

#include static main (){ auto addr = 0x2d28 汽车 我 for (i = 0 i != 21 ++ i ) { Message (%c , Byte (addr + i )^ 0x66 ) } }

探索服务端处理函数

从Java的层分析的逻辑中并没有服务端的线索,而这样层也只有初始化的JNIonload,初始化节还没有探索,这是我们接下来的目标

之一步排除初始化节,所以加载后首先执行的节代码,这里可以看出没有这个节,所以排除,那么就直接分析JNIonload *** ,JAVA中调用loadlibray的时候调用的 ***

JNI_Onload分析:往进 *** 两层,最终调用下面这个函数

int (__cdecl *inti_proc(void))(int){ return inti_proc()}

这个函数一开始就对数据段中一块大小为34291的数据进行异或0x67解密,接着创建线程用socket链接将刚才解密的内容构造称HTTP的响应数据包,一旦有socket链接连接过来就发送这样的数据包回去。

逻辑分析清除,下面我们针对细节进行解决

针对需要解密的字节流,通过IDC脚本进行处理,解密后的数据是HTML页面,使用到了WebAssembly技术,网页汇编的灵魂就是将其他语言如C ^汇编成前端可以解释的语言,即用?语言写页面的一些逻辑。

#include static main (){ auto addr = 0x4004 auto i = 34291 而(i ) { - i 消息(%c , 字节(addr ++ )^ 0x67 ) }}

分析这里的逻辑得知,我们需要让输入内容为32位并且check_key()函数返回结果为1,即可完成这道题

< html > < head > < meta http-equiv = content-type content = text / html; charset = UTF-8 > < meta charset = utf-8 > < style > body { 背景色: RGB (255 , 255 , 255 ) } < script >var 实例WebAssembly 。编译(新的 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 ....... 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 ` 。修剪()。分裂(/ [\ s \ r \ N + /克)。图(STR => parseInt函数(STR , 16 )) ))。然后(module => { new WebAssembly。实例化(模块)。然后(results => { instance = results })。捕捉(控制台。误差)})函数 check_flag (){ VAR 值 = 文档。getElementById (key_value )。价值 如果(值。长度 != 32 ) { 文档。getElementById (tips )。innerHTML = 不正确! 回归 } 实例。出口。set_input_flag_len (值。长度) 为(VAR II = 0 二< 值。长度; 二++ ){ 实例。出口。set_input_flag (value [ ii ] .charCodeAt (),ii ); } var ret = 实例。出口。check_key (); if (ret == 1 ){ document 。getElementById (tips )。innerHTML = 祝贺! } else { document 。getElementById (tips )。innerHTML = 不正确! } } < 体> < DIV >键:< 输入 ID = key_value 类型= 文本 style = width:60% ; = value = > < input type = submit value = check onclick = check_flag() > < div > < label id = tips >

下面我们进入网页汇编来探索内部实现逻辑

webassemble

我们在这部分探索的目标就是先用16进制内容构成对应的WA *** 二进制文件,然后将WA *** 二进制文件转成C,接着生成ELF文件,用IDA进行分析。

先生成data.bin二进制文件

import array , structhexstring = \ x00 \ x61 \ x73 \ x6D \ x01 \ x00 \ x00 \ x00 \ x01 \ x1B \ x05 \ x60 \ x00 \ x00 \ x60 \ x04 \ x7F \ x7F \ x7F \ x7F \ x01 \ x7F \ x60 \ x02 \ x7F \ x7F \ x01 \ x7F \ x60 \ x01 \ x7F \ x01 \ x7F \ x60 \ x00 \ x01 \ x7F ............. \ x6C \ x61 \ x67 \ x0A \ x12 \ X73 \ X65 \ X74 \ X5F \ X69 \ x6E \ X70 \ X75 \ X74 \ X5F \ X66 \ X6C \ X61 \ X67 \ X5F l \ x65 \ x6E \ x0B \ x09 \ x63 \ x68 \ x65 \ x63 \ x6B \ x5F \ x6B \ x65 \ x79 \ x0C \ x03 \ x78 \ x78 \ x78 f = open ('c:\ Users \ xxx \ Desktop \ data.bin' ,'wb' )f 。write (hexstring )f 。关闭()

接着用wa *** 2c.exe生成?文件

wa *** 2c 。exe 数据。bin -o test 。C

直接gcc wa *** .c会报错,因为很多wa *** 的函数没有具体的实现。所以只编译就好了

gcc -c test.c -o test.o

用IDA打开的.o文件

首先 *** 中调用将输入的字符长度保存到内存中,接着将输入的字符也保存到内存0x400的处

接着就是主要的check_key函数,最终目标是XXX函数返回结果为1,即可完成逆向工作

这里前8个?函数对我们输入的32内容依次进行了处理,我们具体分析一下

一重加密

经过简单分析,这里其实是对输入内容进行了异或计算,然后将结果替换内存中原来的数据。下面图中的条件是肯定满足的,因为我们输入的内容在33到127之间,最小的33 * 4也等于132肯定不为-1时,这个语句恒执行其他的内容,至于其余几个都是相同的内容,即在这里对输入内容进行之一次加密

32元线性方程组

接着我们分析XXX函数,我们的目标也是满足XXX函数返回值为1

从内存中奖一重加密后的输入内容读取到变量中,可以看到顺序做过修改

接下来就是下图中看到的32元方程组,如果有兴趣和数学基础的同学可以用矩阵解法写个类似的小脚本,这里我用到的是Z3库解决

解密

一重解密

PIP安装Z3求解器

接着用蟒脚本写一个求解语句,先初始化32个变量,接着将IDA的内容拷贝过来,将符号修改一下即可

#* - *编码:utf-8 - * - 来自 z3 进口 *#生面32元变量v5 = Int ('m53' )v6 = Int ('m52' )v7 = Int ('m51' )v8 = Int ('m50' )v9 = Int ('m49' )v10 = Int ('m48' )v11 = Int ('m47' )v12 = Int ('m46' )v13 = Int ('m45' )V14 = 诠释('M44' )V15 = 诠释('M43' )V16 = 诠释('M42' )V17 = 诠释('M41' )V18 = 诠释('M40' )V19 = 诠释('M39' )V20 = Int ('m38' )v21 = Int ('m37' )v22 = Int ('m36')v23 = INT ('M35' )V24 = INT ('M34' )V25 = INT ('M33' )V26 = INT ('M32' ) V27 = INT ('M31' )V28 = INT ('M30' )V29 = INT ('m29' )v30 = Int ('m28' )v31 = Int ('m27')v32 = Int ('m26' )v33 = Int ('m24' )v34 = Int ('m25' )v35 = Int ('m55' )v36 = Int ('m54' )#实例化一个求解器对象s = 求解器()s 。添加(和(45 * v5 + 248 * v6 + 20 * v7 + 67 * v8 + 90 * v9 + 135 * v10 + 106 * v11 + 112 * v12 + 40 * v13 + 231 * v14 + 153 * v15 + 233 * v16 + 19 * v17 + 188 * V18 + 232 * V19 + 127 * V20 + 15 * V21 + 67 * V22 + 50 * V23 + 161 * V24 + 103 * V25 + 144 * V26 + 81 * V27 + 126 * V28 + 240 * V29 + 124 * v30 + 194 * v31 + 92 * v32 + 108 * v33 + 111 * v34 + 174 * v35 + 48 * v36 == 359512 ..... , 244 * v5 + 196 * v6 + 30 * v7 + 100 * v8 + 168 * v9 + 7 * v10 + 249 * v11 + 84 * v12 + 252 * v13 + 171 * V14 + 210 * V15 + 206 * V16 + 108 * V17 + 153 * V18 + 67 * V19 + 189 * V20 + 141 * V21 + 239 * V22 + 177 * V23 + 10 * V24 + 15 * V25 + 164 * v26 + 142 * v27 + 97 * v28 + 27 * v29 + 173 * v30 + 146 * v31 + 133 * v33 + 105 * v34 + 75 * (v32 + v35 ) + 197 * v36 == 393331 ))s 。添加(185 * v5 + 196 * v6 + 135 * v7 + 218 * (v24 + v9 ) + 241 * v8 + 210 * v10 + 127 * v11 + 221 * v12 + 47 * v13 + 179 * v14 + 61 * v15 + 59 * v16 + 197 * v17 + 204 * v18 + 198 * v19 + 75 * v20 + 146 * v21 + 156 * v22 + 235 * v23 + 63 * v25 + 220 * v26 + 3 * v27 + 167 * v28 + 230 * v29 + 69 * v30 + 186 * v31 + 57 * v32 + 147 * v33 + 221 * v34 + 79 * v35 + 53 * v36 == 430295 )#sat表示计算出结果if s 。check () == sat : t = [ print compute result: m = s 。model () t 。追加(str (m [ v33 )) t 。追加(str (m [ v34 )) t 。追加(str (m [ v32 )) t 。追加(str(m [ v31 )) t 。追加(str (m [ v30 )) t 。追加(str (m [ v29 )) t 。追加(str (m [ v28 )) t 。追加(str (m [ v27 )) t 。追加(str (m [ v26 )) t 。追加(str (m [ v25 )) t 。追加(str (m [ v24 )) t 。追加(str (m [ v23 )) t 。追加(str (m [ v22 )) t 。追加(str (m [ v21 )) t 。追加(str (m [v20 )) t 。追加(str (m [ v19 )) t 。追加(str (m [ v18 )) t 。追加(str (m [ v17 )) t 。追加(str (m [ v16 )) t 。追加(str (m [ v15 )) t 。追加(str (m [ v14 )) t 。追加(str (m [ v13 )) t 。追加(str (m [ v12 )) t 。追加(str (m [ v11 )) t 。追加(str (m [ v10 )) t 。追加(str (m [ v9 )) t。追加(str (m [ v8 )) t 。追加(str (m [ v7 )) t 。追加(str (m [ v6 )) t 。追加(str (m [ v5 )) t 。追加(str (m [ v36 )) t 。追加(str (m [v35 )) t = map (int , t ) t = map (chr , t ) print 。加入(t )否则: 打印 失败

二重解密

这里直接用的大佬的脚本,将上面解密的数据进行异或计算,即可返回最终我们需要输入的内容

int main (int argc , char ** argv ) { unsigned char c [ 33 = S0m3time_l1tt1e_c0des_us3ful33 无符号 字符 在[ 33 = { 0 } unsigned int t1 = 0 ,t2 = 0 ,t3 = 0 ,t4 = 0 printf ((const char * )c ) printf ( \ n ) 在[ 0 = c [ 0 ^ 0x18 在[ 1 = c [ 1 ^ 0x9 在[ 2 = c [ 2 ^ 0x3 在[ 3 = c [ 3 ^ 0x6b 在[ 4 = c [ 4 ^ 0x1 在[ 5 = c [ 5 ^ 0x5A 在[ 6 = c [ 6 ^ 0x32 在[ 7 = c [ 7 ^ 0x57 在[ 8 = c [ 8 ^ 0x30 在[ 9 = c [ 9 ^ 0x5d 在[ 10 = c [ 10 ^ 0x40 在[ 11 = c [ 11 ^ 0x46 在[ 12 = c [ 12 ^ 0x2b 在[ 13 = c [ 13 ^ 0x46 在[ 14 = c [ 14 ^ 0x56 在[ 15 = c [ 15 ^ 0x3d 在[ 16 = c [ 16 ^ 0x02 在[ 17 = c [ 17 ^ 0x43 在[ 18 = c [ 18 ^ 0x17 在[ 19 = c [ 19 在[ 20 = c [ 20 ^ 0x32 在[ 在[21 = c [ 21 ^ 0x53 在[ 22 = c [ 22 ^ 0x1F 在[ 23 = c [ 23 ^ 0x26 在[ 24 = c [ 24 ^ 0x2a 在[ 25 = c [ 25 ^ 0x01 在[ 26 = c [ 26 在[ 27 = c [ 27 ^ 0x10 在[ 28 = c [ 28 ^ 0x10 在[ 在[29 = c [ 29 ^ 0x1E 在[ 30 = c [ 30 ^ 0x40 在[ 31 = c [ 31 printf ((const char * )in ) 返回 0 }小结

【1】多元线性方程式可以通过python的z3-solver库快速计算

反思

最开始做这道题我是卡在了最后一步,我用鼠尾草并未求出结果。

主要原因是:我甚至未能清除的理解这个算法的本质,当时并未意识到这是个多元方程求解的计算,只想着怎么求出这个结果,结果在网上找到一个相似题的解决 *** ,用鼠尾草计算,但在这里却并未算出

结论:解决问题时,不要求对所有细节了如执掌,但是题的主干脉络,根本思路是我们需要探索的

参考

【1】[原创第五题:的丛林秘密https://bbs.pediy.com/thread-252191.htm

【2】Python中的Z3 API https://nen9ma0.github.io/2018/03/14/z3py/

【3】IDC脚本 - IDC脚本语言官方教程 https://bbs.pediy.com/thread-219016.htm

【4线性】方程组矩阵解法https://www.shuxuele.com/algebra/systems-linear-equations-matrices.html

钗头凤中的意象,长头发真的影响智力吗


    收藏永久发布页,不迷路
    关键词不能为空

免责声明:

本站提供的资源,都来自网络,版权争议与本站无关,所有内容及软件的文章仅限用于学习和研究目的。不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负,我们不保证内容的长久可用性,通过使用本站内容随之而来的风险与本站无关,您必须在下载后的24个小时之内,从您的电脑/手机中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。侵删请致信E-mail: 1470282@qq.com

我来说两句
签到
热门文章
随机推荐
交流杂谈 穿堂风真的影响家人的健康吗(长头发真的影响智力吗)
多元方程是什么意思,长头发真的影响学习吗 今天周五了,不知道大家想看点什么,Tiger就更新一个CTF的多元线性方程吧,前阵子HW闹的好多话不敢说,下周正常恢...
扫描二维码阅读原文 扫描二维码阅读原文
牛蛙资源网 January, 01
生成社交图 ×