首页
论坛
专栏
课程

[原创 ]KCTF 2019 Q2 第五题 越过山丘

2019-6-24 21:26 3325

[原创 ]KCTF 2019 Q2 第五题 越过山丘

HHHso
16
2019-6-24 21:26
3325

一、序幕

Apk,走流程

(1)     zip解压

(2)     apktool转jar,未成功,无关紧要

lib目录结构,想来应该使用了NDK的JNI,选个简单熟悉的架构,x86拖进IDA

├─arm64-v8a

│      libgogogo.so

├─armeabi-v7a

│      libgogogo.so

├─x86

│      libgogogo.so

└─x86_64

        libgogogo.so

与此同时,也把zip解压出来的classes.dex直接拖进另一个IDA

二、成功之母

在classes.dex的响应函数中,我们看到了对JNI的check_key调用,并根据结果判断是否正确,成功入套。




按上面的逻辑,一眼望过去,应该不合逻辑,

因为可以个字节要么是0x00(False),要么是0x01(True),

我们得到key的十六进制编码如下,显然不合逻辑,这一步是做完后补充测试的结果,

因为题目要求特定新版本以上,我们有理由怀疑不同版本的srand和rand实现不同,会有影响,但实际可能是多想了。

可能就是新版的WebView一类的功能控件。


一、偶遇后门

在随机浏览lib库函数中,我们不经意留意到下面竟然开启侦听

神经过敏的感觉是:作者竟然在样例中安插后门!怀着应该不存的好奇心理看下这“后门”干啥

(1)     手机A(扮演路由)提供热点HotPoint

(2)     PC的wifi连接上HotPoint

(3)     安装该apk样例的手机B也连接上HotPoint

(为啥不直接在手机A上安装apk?这个随意)




我们curl一下(其它工具也行,随意,只是顺手拿起curl)看下apk后门返回啥,如图,

怪怪的,莫非是攻击载荷?当然,WebAssembly关键字高速我们,应该内有乾坤



四、疑车无据

正常的套路,我们应该按apk的启动顺序,逐个看下相关的函数

如从下面的MainActivity.OnCreate里我们看到,实际上作者在设计时在layout上弄了一套EditText,View,Button的界面输入三件套

但实际其是使用的陷阱,作为伪装,或者是最初的设计原型;

实际主要通过WebView的loadUrl加载 mainActivity_u的URL内容工作,mainActivity_u由JNI 的sayHello返回 http://127.0.0.1:8000

即,前面的后门是为自己开的,除非别人也知道,且还能POC进去。

这个是攻击完成后补充分析,先上的船,后面补的票。当然,正常套路,应该是先买票,按部就班,再上船。

在攻击时,并不知道android有WebView这东西,也不晓得WebAssembly是啥,毕竟不搞android和web开发

当然,职业直接告诉我们WebAssembly应该是种汇编语言。

实际上完成攻击并不是主要目标,这后门和WebAssembly成了好奇点,好奇害死猫。

这apk的后门没啥新奇,就开启侦听,返回页面内容,我们看下返回的内容完整是啥。




四、Html



我们可以看到,其返回的Hi_Ptr2HtmlContent_off_2F94内容,并不像我们在前面通过【curl 192.168.43.27:8000】敲门拿到的内容,

应该是加密了。再多看一眼后门的代码,显然,都是通过xor 0x67进行异或加密和解密。



直接上,在IDAPython里执行【for i in range(34290):  PatchByte(0x3004+i,GetOriginalByte(0x3004+i)^0x67)】

fstr = ''.join([chr(GetOriginalByte(0x3004+i)^0x67) for i in range(34290)])
with open(r'.\index.html','wb') as fout:
  fout.write(fstr)

我们解密得到需要的内容

我们保存为index.html,如下(其中省略了WebAssembly的字节内容,全文参考附件index.html)

我们用浏览器打开,效果如图,有意思,竟然和apk交互一样。


<!DOCTYPE html>
<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
------- ------- ------- ------- ------- ------- -------
------- ------- -------   省略  ------- ------- -------
------- ------- ------- ------- ------- ------- -------
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(/[\s\r\n]+/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 之路

三个参考页面内容

import base64
#页面1
base64.b64decode('aHR0cHM6Ly9saW1iZW5qYW1pbi5jb20vYXJ0aWNsZXMvZmxhcmUtb24tNS13YXNtLXdpdGgtY2hyb21lLmh0bWw=')
#页面2
base64.b64decode('aHR0cHM6Ly93d3cuY25ibG9ncy5jb20vd29vZHpjbC9wLzc0Nzg3OTIuaHRtbA==')
#页面3
base64.b64decode('aHR0cHM6Ly93d3cueGQxMDA4Ni5jb20vcG9zdHMvMjMyOTYyNTM2OTAzNTIyNTc2Lw==')

其中第一个页面内容告诉我们,Chrome竟然可以调试WebAssembly,当然,Script层是可以调试的。WebAssembly层怎么进去,未曾深究模仿。

【需要声明,此图片内容归原页面作者所有】



很不幸,Chrome用F12后我们的内容跟上图的有些出入,我们没有WebAssembly文件。

所以我们要处理一下,我们把WebAssembly的字节转换为二进制wasm文件,


我们将WebAssembly中的内容复制出来,

如下图,其中省略部分内容(参考附件d.py文件)保存为python文件,通过执行【python d.py】同目录下,我们得到WebAssembly的编译二级制文件wasmkc.wasm



我们参考上述第二个页面的内容,将index.html修改为引用外部WebAssembly文件的方式,如下图;

(这个可能需要将index_wasm.html和wasmkc.wasm放自己的服务器才能正常执行)


于是我们看到了我们的wasm内容


还有其对应的反汇编


实际上,通过给IDA装上相应的WebAssembly反编译模块(Python模块脚本),也可以得到WebAssembly的反汇编,

如图,不过如果对wasm的文件格式不熟悉,可能会有些蒙,其反汇编效果一般,无法识别内嵌模块是否隶属同一个函数。

IDA的wasm python反编译脚本github 【base64.b64decode('aHR0cHM6Ly9naXRodWIuY29tL2ZpcmVleWUvaWRhd2FzbQ==')】

这个是参考wasm文件格式原义,结合IDA解读并命名后的效果,直接IDA反编译得不到这些效果,如函数名称。


可以突击下官方的WebAssembly汇编,MVP初始版本支持简单的指令集,操作码非常有限。




此外,010 也能辅助了解一wasm的二进制格式


六、回到过去

第三个页面直接介绍了WebAssembly的实战攻击,攻击面会回到WebAssembly的过去。

Github有WebAssembly的官方工具集合wabt,编译一份

└─bin

        spectest-interp.exe

        wasm-interp.exe

        wasm-objdump.exe

        wasm-opcodecnt.exe

        wasm-strip.exe

        wasm-validate.exe

        wasm2c.exe

        wasm2wat.exe

        wast2json.exe

        wat-desugar.exe

        wat2wasm.exe

可以用wasm2wat.exe得到WebAssembly汇编。

也可以用wasm2c.exe得到反编译的c代码。

usage: wasm2c [options] filename

  Read a file in the WebAssembly binary format, and convert it to
  a C source file and header.

examples:
  # parse binary file test.wasm and write test.c and test.h
  $ wasm2c test.wasm -o test.c

  # parse test.wasm, write test.c and test.h, but ignore the debug names, if any
  $ wasm2c test.wasm --no-debug-names -o test.c

options:
  -v, --verbose                               Use multiple times for more info
      --help                                  Print this help message
  -o, --output=FILENAME                       Output file for the generated C source file, by default use stdout
      --enable-exceptions                     Enable Experimental exception handling
      --disable-mutable-globals               Disable Import/export mutable globals
      --enable-saturating-float-to-int        Enable Saturating float-to-int operators
      --enable-sign-extension                 Enable Sign-extension operators
      --enable-simd                           Enable SIMD support
      --enable-threads                        Enable Threading support
      --enable-multi-value                    Enable Multi-value
      --enable-tail-call                      Enable Tail-call support
      --enable-bulk-memory                    Enable Bulk-memory operations
      --enable-reference-types                Enable Reference types (anyref)
      --enable-annotations                    Enable Custom annotation syntax
      --no-debug-names                        Ignore debug names in the binary file
expected filename argument.

结合wasm的几个头文件,通过【gcc -c wasmkc.c】编译到obj文件

wasm-rt-impl.c

wasm-rt-impl.h

wasm-rt.h

wasmkc.o 文件放进IDA反编译,我们得到经过编译器各种优化机制处理后的等价代码逻辑,

在Script中,要求key长度为32,其分别调用WebAssembly的三个导出函数进行业务逻辑处理

前两个负责传递keylen和key数据,最后一个负责校验,对应的c代码逻辑参考IDA相应截图





可见,check_key对key分成八部分,进行变换,最后通过xxx函数处理

八个【_o+】系列的函数内部逻辑相对比较简单,实际是对八个部分分别xor异或处理。

以【_o】为例,我们只需要关注伪码函数体开始和尾部部分即可,中间部分为干扰。

逻辑相对清晰,加载各个key的字节,然后xor上因子再回存。

我们只需提取八个【_o*】函数对应key的总共32个xor因子即可。



从函数体尾部,我们得到[0x18,0x09,0x03,0x6B]


xk = [0x18,0x09,0x03,0x6b] + [0x01,0x5a,0x32,0x57] +[0x30,0x5d,0x40,0x46] +[0x2b,0x46,0x56,0x3d] +[0x02,0x43,0x17,0x00] +[0x32,0x53,0x1f,0x26] +[0x2a,0x01,0x00,0x10] +[0x10,0x1e,0x40,0x00]

在xxx函数中,我们可以看到是32元一次方程,共32个,所以有唯一解,解出来后,在xor上xk即可得到输入key。

这里我们用python自动处理xxx的伪码文本,提取出32元一次方程组,并借助sympy进行解方程。

#加载伪码文本
with open(r'.\xxx.c','rb') as fin:
  ls = fin.readlines()

#处理伪码函数头部的未知数,这里我们以1024为x0,1025为x1,以此类推,ekey即为 [x0,x2,x3,...x31]
#这里会生成伪码中局部变量v**对应的x**关系自动vn2xn,如下图的v30对应x0
import re
prog = re.compile(r'(?s) *(\S+)=i32_load8_s.*memory,(\S+),.*')
vn2xn = {}
for l in ls:
  m = prog.match(l)
  if m is not None:
    vn,xi = m.groups()
    xn = 'x{}'.format(int(xi,10)-1024)
    print "{} is {}".format(vn,xn)
    if vn not in vn2xn:
      vn2xn[vn]=xn
    else:
      raise Exception("vn repeat")

vs = vn2xn.keys()
vs = [int(v[1:]) for v in vs]
vs.sort()

#完成方程式中v**变量大x**的替换
def v2x(xe):
  global vn2xn
  for v in vs[::-1]:
    vn = "v{}".format(v)
    xe = xe.replace(vn,vn2xn[vn])
  return xe


#我们通过对xxx.c伪码中各方程组开头固定为&&标记,并将一下非未知数的V**变量替换为其对应的常量
#然后通过正则批评提取方程组
a = r'(?sm)&&(.*?)==([0-9]+)'
#b = r'(?sm)(?=if\()(.*?)==([0-9]+)'
#c = r'(?sm)(?=v34=)(.*?)==([0-9]+)'
for m in re.finditer(a, fstr):
  #print m.groups()
  e,r =  m.groups()
  xe = '{}=={}'.format(e.replace('\r','').replace('\n','').replace(' ',''),r)
  print v2x(xe)

#提取到的32个方程组如下

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

通过代码生成代码,通过下面代码,生成32个x0,x1,...,x32的未知数符号声明代码,然后复制粘贴到python里执行
from sympy import Symbol
from sympy import solve

for xi in range(0,32):
  print "x{}=Symbol('x{}')".format(xi,xi)

x0=Symbol('x0')
x1=Symbol('x1')
x2=Symbol('x2')
x3=Symbol('x3')
x4=Symbol('x4')
x5=Symbol('x5')
x6=Symbol('x6')
x7=Symbol('x7')
x8=Symbol('x8')
x9=Symbol('x9')
x10=Symbol('x10')
x11=Symbol('x11')
x12=Symbol('x12')
x13=Symbol('x13')
x14=Symbol('x14')
x15=Symbol('x15')
x16=Symbol('x16')
x17=Symbol('x17')
x18=Symbol('x18')
x19=Symbol('x19')
x20=Symbol('x20')
x21=Symbol('x21')
x22=Symbol('x22')
x23=Symbol('x23')
x24=Symbol('x24')
x25=Symbol('x25')
x26=Symbol('x26')
x27=Symbol('x27')
x28=Symbol('x28')
x29=Symbol('x29')
x30=Symbol('x30')
x31=Symbol('x31')

#同理,我们通过代码生成解方程的python代码,并执行得到结果r
exs = []
for m in re.finditer(a, fstr):
  #print m.groups()
  e,r =  m.groups()
  xe = '{}-{}'.format(e.replace('\r','').replace('\n','').replace(' ',''),r)
  exi = v2x(xe)
  exs.append(exi)

estr = 'solve([{}],[{}])'.format(','.join(exs),','.join(['x{}'.format(xi) for xi in range(32)]))
r = eval(estr)

#提取r中的各个结果,即可到ekey,再与我们的xk异或解密得到输入的key
'[{}]'.format(','.join(['r[x{}]'.format(i) for i in range(32)]))
ek = [83, 48, 109, 51, 116, 105, 109, 101, 95, 108, 49, 116, 116, 49, 101, 95, 99, 48, 100, 101, 95, 49, 115, 95, 117, 115, 51, 102, 117, 108, 51, 51]
xk = [0x18,0x09,0x03,0x6b] + [0x01,0x5a,0x32,0x57] +[0x30,0x5d,0x40,0x46] +[0x2b,0x46,0x56,0x3d] +[0x02,0x43,0x17,0x00] +[0x32,0x53,0x1f,0x26] +[0x2a,0x01,0x00,0x10] +[0x10,0x1e,0x40,0x00]

>>> [chr(int(ek[i])^xk[i]) for i in range(32)]
['K', '9', 'n', 'X', 'u', '3', '_', '2', 'o', '1', 'q', '2', '_', 'w', '3', 'b', 'a', 's', 's', 'e', 'm', 'b', 'l', 'y', '_', 'r', '3', 'v', 'e', 'r', 's', '3']
>>> ''.join([chr(int(ek[i])^xk[i]) for i in range(32)])
'K9nXu3_2o1q2_w3bassembly_r3vers3'









[公告]安全服务和外包项目请将项目需求发到看雪企服平台:https://qifu.kanxue.com

最后于 2019-6-27 09:00 被HHHso编辑 ,原因:
上传的附件:
最新回复 (2)
elecs 2 2019-6-27 18:48
2
0
当初卡在调试wasm上,谢谢您的分享。
bluth 2019-7-2 11:12
3
0
 
最后于 2019-7-4 15:33 被bluth编辑 ,原因:
游客
登录 | 注册 方可回帖
返回