吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 16518|回复: 76
收起左侧

[Web逆向] 某5影视ts视频wasm加密分析(wasm逆向)

  [复制链接]
Frhvjhhv 发表于 2021-2-28 17:18
首先,f12,可以看到网站很卡。是因为这个网站有脏代码,监听了f12,然后pushstate,即疯狂的向地址栏中写入数据,把内存占满。解决办法是hook pushstate。
然后就可以跟踪了。

跟踪的一个关键地方:
[JavaScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
d.prototype.processSegment = function(e, t, i, n) {
                        var r = d.nup.Module;
                        this.mem || (this.mem = r._malloc(131072));//1
                        for (var a = 0; a < n; ) {
                            var o = Math.min(n - a, 131072);//2
                            r.HEAPU8.set(t.slice(a, a + o), this.mem),//3
                            this._processSegment(e, this.mem, i + a, o),//4
                            t.set(r.HEAPU8.slice(this.mem, this.mem + o), a),
                            a += o
                        }
                    }



上述代码1处是分配131072大小的内存,返回的数据就是分配的内存的起始地址(这个网站默认地址为6472960),3处是把视频数据分割成131072大小,然后塞入之前已经实例化的wasm内存中,视频的起始指针就是之前分配的内存的起始地址。
4处的参数就两个关键的地方:即视频在wasm的起始地址和视频在wasm的内存中的长度。
跟进4处,他往wasm的内存中又写了一些数据,这里先按下不表,然后就进入了关键的函数:
[Asm] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
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
(func $_nup2p_process_segment (;236;) (export "_nup2p_process_segment") (param $var0 i32) (param $var1 i32) (param $var2 i32) (param $var3 i32)
   (local $var4 i32) (local $var5 i32)
   global.get $global9
   local.set $var4
   global.get $global9
   i32.const 16
   i32.add
   global.set $global9
   global.get $global9
   global.get $global10
   i32.ge_s
   if
     i32.const 16
     call $abortStackOverflow
   end
   local.get $var4
   i32.const 4
   i32.add
   local.tee $var5
   local.get $var0
   i32.store
   local.get $var4
   local.get $var1
   i32.store
   local.get $var0
   if
     local.get $var5
     call $__ZNSt3__26__treeINS_12__value_typeIi14nup2p_secret_tEENS_19__map_value_compareIiS3_NS_4lessIiEELb1EEENS_9allocatorIS3_EEE4findIiEENS_15__tree_iteratorIS3_PNS_11__tree_nodeIS3_PvEElEERKT_
     local.tee $var0
     i32.const 104472
     i32.ne
     if
       local.get $var0
       i32.load8_s offset=44
       if
         local.get $var1
         local.get $var3
         local.get $var4
         local.get $var0
         i32.const 20
         i32.add
         local.get $var2
         call $_decode_bcrypto_buf
         drop
       end
     end
   end
   local.get $var4
   global.set $global9
 )



在上面的wasm代码中,__ZNSt3__26__treeINS_12__value_typeIi14nup2p_secret_tEENS_19__map_value_compareIiS3_NS_4lessIiEELb1EEENS_9allocatorIS3_EEE4findIiEENS_15__tree_iteratorIS3_PNS_11__tree_nodeIS3_PvEElEERKT_和_decode_bcrypto_buf很重要
wasm代码肯定是要跟着走一遍的,然后配合jeb和IDA分析。首选jeb。因为jeb对wasm的反汇编代码质量很高,阅读性好。但是这个例子中因为导入了很多函数,而且频繁的操作内存,所以jeb会报错。只能用ida了。关键还是看懂wam的汇编代码,走一遍。
wasm很简单,不懂的指令查官网就行了  https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md
在这里我要说的指令就两个:i32.load。和i32,store。wasm要想操作内存,就只能用这两个指令。(i32.load8,i64.load8,i32.load16,offset=7等等原理都是一样的)。i32.load就是加载一个四个字节的数,注意wasm的字节都是以小端存储的
2f5f8ab66c694617e244b24f316f86c.png

在这里,执行i32.load之前,堆栈里的数是104472.那么我们就要去找内存地址104472,然后加载四个字节


9f958209158f4257a8deb6ab8b6e4f1.png
可以看到这四个数分为152,196,98,0
我们把他们转化为二进制:
152:10011000
196:11000100
98  :   1100010
0    :    0
由于是小端存储,所以低地址在前,高地址在后
所以加载的数的二进制表示形式是:0|1100010|11000100|10011000(|为分隔符)
转换为十进制为6472856
检验一下:
111e2eacd521434546fb106845ac86d6a3.png

可以看到是正确的。

然后继续跟踪下去。这里放上我跟踪一遍之后的伪代码:
[JavaScript] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
int memory[134217728]={}
nup2p_process_segment(int var0, int var1,int var2,int var3)
int var4,var5;
var4=global9=107696
global9+=16
global10=5350544
if(global9>globa110)
{
  $abortStackOverflow(16);
}
var 5=var4+4   //var 0=11,,var 5=10770x
var0=memory[var5]
var1=memory[var4]//var1=6472960
if(var0!=undefined)
{
     var0=$__ZNSt3__26__treeINS_12__value_typeIi14nup2(var5)//6468856
     if (var0!=104472)
     {
         if(memory[var0+44]!=undefined)
             {       //var2=786432;var0+20=6468820;var3=131072;var1=6472960;var4=107696
                 decode_bcrypto_buf(var1,var3,var4,var0+20,var2)
                             
             }
     }
}
 
 
 
           //                         6468876 
           //6472960  131072  107696  6468820  786432
decode_bcrypto_buf(var0,var1,var2,var3,var4)
int var6,var7,var8,var9=0;
if(var3)
{
    if(memory[var3+4])
       {
           var5=memory[var3+6]  //8
           var8=65535&&var5     //8
           if(var5)
           
               var5=memory[var2];  //8
               if(var5)
               {
                  var2=var5      //8
                
               //647290  71
               else
               {
                 cc=var2
                 var2=call $__Znam(var1)
                 memory[var2]=cc;
                
               }
               var10=var1>>3;//131072>>3=16384
               var5=var4;
                  for()
                      //  6468884: 80   98
                         if(var9!=var10)
                         {
[color=red]                         memory[var2+var7]= //6472960
                             memory[var0+var7]^memory[(var3+8)+(var5%var8)] ;  35^memory[6468876+0](80) //(1)[/color]
                            memory[ var2+(var6=var7|1)]=//6472960+(0|1)
                             (memory[var0+var6])^memory[(var3+8)+(var5+1)%8]   //6468885
                              
                            memory[ var2+(var6=var7|2)]
                            (memory[var0+var6]) ^memory[(var3+8)+(var5+2)%8]     memory[6468876+8+(2)](89)
                         }
                      }
           }
       }
}
 
 
$__ZNSt3__26__treeINS_12__value_typeIi14nup2(var0)//107700
int var1,var2;
block1;
{
var1=104472;
//memory[var1];//6468800
var2=$__ZNSt3__26__treeINS_12__value_typeIi14nup2p_secret_tEEN(var0,memory[var1],var1)//var2=648856
if(var2==104472)
{goto block1; }
if(memory[var2+16]<memory[var0])
{goto block1;}
var1=var2;
}
return var1;
 
 
 
 
 
$__ZNSt3__26__treeINS_12__value_typeIi14nup2p_secret_tEEN(var0,var1,var2)//107700  6468800  104472
[color=red]int var3=memory[var0];//12 (2)[/color]
for (var1>0)    
{
        var2=memory[var1+16]<var3? var2:var1;//11<12     12==12     6468856
        var0=memory[var1+16]<var3;//1       0
        var1=memory[var0? var1+4:var1]//6468856
}
return var2//6468800
        //6468856




跟踪一遍可以发现在decode_bcrypto_buf函数的1处,他对于原来的视频数据每隔8个字节为一组。分别对这一组的每个字节进行了一次异或,然后覆盖了原来的字节,其中关键的参数是var3+8这个内存地址的数据。var5能被8整除。所以异或的第二个参数就是0,1,2一直到8。所以原来的视频数据每隔8个字节为一组,这一组的每个字节分别与var3+8,var3+8+1,var3+8+2等等一直到vae3+8+7的地址处的数据进行异或。
,var3var3最终是在
$__ZNSt3__26__treeINS_12__value_typeIi14nup2p_secret_tEEN(var0,var1,var2)这个函数的2处进行调用的。
ec6c10cd73146884733ed7318521461.png
多次跟踪可以发现,内存地址不固定,而且内存地址的值不固定。
所以,内存地址的值就是在最前面按下不表那里写入的。
跟踪可以发现
[JavaScript] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
string: function(e) {
     var t = 0;
     if (null != e && 0 !== e) {
         var i = 1 + (e.length << 2);
         stringToUTF8(e, t = stackAlloc(i), i)
     }
     return t
 },



其中,e = "http://0.0.0.0“,stringToUTF8首先是望wasm的前14个字节写入了一些数据stackAlloc函数调用的是wasm代码:
[Asm] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(func $stackAlloc (;165;) (export "stackAlloc") (param $var0 i32) (result i32)
   (local $var1 i32)
   global.get $global9
   local.set $var1
   local.get $var0
   global.get $global9
   i32.add
   global.set $global9
   global.get $global9
   i32.const 15
   i32.add
   i32.const -16
   i32.and
   global.set $global9
   global.get $global9
   global.get $global10
   i32.ge_s
   if
     local.get $var0
     call $abortStackOverflow
   end
   local.get $var1
 )



翻译成伪代码为:
stackAlloc(var0) //  57
global9=107696
var1=107696
global9=var0+global9
global9=(global9+15)^(-16)
globa110=5350544
if(global9>globa110)
{
   abortStackOverflow(var0);
}   
return var1

最终可以发现是调用的这句话填充数据的:
[Asm] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
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
(func $_nup2p_start (;179;) (export "_nup2p_start") (param $var0 i32) (param $var1 i32)
    (local $var2 i32)
    i32.const 104424
    i32.load
    i32.eqz
    if
      i32.const 128
      call $__Znwm
      local.set $var2
      i32.const 0
      global.set $global5
      i32.const 65
      local.get $var2
      local.get $var0
      local.get $var1
      call $invoke_viii
      global.get $global5
      local.set $var0
      i32.const 0
      global.set $global5
      local.get $var0
      i32.const 1
      i32.and
      if
        call $___cxa_find_matching_catch_2
        local.set $var0
        call $getTempRet0
        drop
        local.get $var2
        call $__ZN8CryptoPP19UnalignedDeallocateEPv
        local.get $var0
        call $___resumeException
      else
        i32.const 104424
        local.get $var2
        i32.store
        i32.const 44
        call $__Znwm
        local.tee $var0
        i64.const 0
        i64.store
        local.get $var0
        i64.const 0
        i64.store offset=8
        local.get $var0
        i64.const 0
        i64.store offset=16
        local.get $var0
        i64.const 0
        i64.store offset=24
        local.get $var0
        i64.const 0
        i64.store offset=32
        local.get $var0
        i32.const 0
        i32.store offset=40
        local.get $var0
        call $__ZN2nu5FilesC2Ev
        i32.const 104428
        local.get $var0
        i32.store
        i32.const 104424
        i32.load
        local.get $var0
        call $__ZN2nu6Engine9addPluginEPNS_6PluginE
      end
    end
  )

而这里面又调用了其他的函数,所以慢慢分析是最终是可以解出他是如何填充数据的,但是太慢了。我们跳出来看看他解密前后的数据:
4a957893e32f097c2383b4036cdb970.png
可以看到解密后的数据中从第22个开始就是255.已知视频是每八个一组进行解密。那么我们从第24个开始分别让原来的视频数据与155进行异或,往后推8个,不就得到了那8个异或的参数?
说干就干
,在上图第一个断点处拦截一下,然后console处运行:

[JavaScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
var array = Array.from(t)
arr=[array[24]^255,array[25]^255,array[26]^255,array[27]^255,array[28]^255,array[29]^255,array[30]^255,array[31]^255]
arra=new Uint8Array(array.length)
for (var ii=0; ii<array.length;ii+=8)
{
for(var j=0;j<8;j++)
{arra[ii+j]=(array[ii+j]^arr[j]);}
 
 
 
}
 
var blob2 = new Blob([arra]);var aaaa = document.createElement('a');
var url2 = window.URL.createObjectURL(blob2);
var filename ="vv.mp4";
aaaa.href = url2;
aaaa.download = filename;
aaaa.click();



视频下载下来了,打开一下:
2250d034a8bbce1474de5383097d241.png



成功!


免费评分

参与人数 27吾爱币 +25 热心值 +24 收起 理由
涛涛不绝00 + 1 + 1 我很赞同!
mzw793600 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
rekaytang + 1 + 1 我很赞同!
yi025 + 1 + 1 谢谢@Thanks!
tonyiyong + 1 + 1 我很赞同!
s67927 + 1 + 1 我很赞同!
ttao88 + 1 我很赞同!
cpj1203 + 1 + 1 谢谢@Thanks!
MasterW + 1 我很赞同!
别说再见 + 1 + 1 谢谢@Thanks!
52poeji131 + 1 + 1 我很赞同!
a6445141 + 1 热心回复!
qaz007 + 1 + 1 用心讨论,共获提升!
wangyaoqianjin + 1 我很赞同!
inter2020 + 1 谢谢@Thanks!
王安1 + 1 热心回复!
在线小学生 + 1 + 1 我很赞同!
hackerchen + 1 + 1 鼓励转贴优秀软件安全工具和文档!
aoran001 + 1 + 1 谢谢@Thanks!
笙若 + 1 + 1 谢谢@Thanks!
姚小宝 + 3 + 1 我很赞同!
塞北的雪 + 1 + 1 想知道如何hook pushstate,求更
OVVO + 1 用心讨论,共获提升!
度娘灬魂手 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
夜泉 + 1 谢谢@Thanks!
漁滒 + 3 + 1 我很赞同!
ofo + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

凌晨四点半 发表于 2021-3-2 15:58
这种没意思
FUCKPINKGUN 发表于 2021-3-21 18:35
不错不错,感觉这思路也可以套用在其他在线影视网站上,比如PH之类……
逍遥一仙 发表于 2021-2-28 23:31
挺好的,方法和我想一块去了。下载可以用我下载器插件来处理。
nonamer 发表于 2021-3-1 09:02
谢谢楼主分享~
我总是用菊花 发表于 2021-3-1 02:13
请问一下hook pushstate 要怎么操作==
a3322a 发表于 2021-3-1 06:51
这加密者也是费了不少功夫
羋羋羋 发表于 2021-3-1 06:56
好文要顶!
wzz131 发表于 2021-3-1 07:17
学习一下,试试手!
km7687547 发表于 2021-3-1 08:32
学习一下,试试手!
dj215 发表于 2021-3-1 08:43
啥脏代码啊~
临时户口 发表于 2021-3-1 09:11
是破解了以后跳过下载ts直接下载到视频源MP4格式的吗?
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-3-17 21:39

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表