爱内涵易语言

 找回密码
 立即注册

在线
客服

会员永久免费学习服务时间: 9:00-24:00

选择下列客服马上在线沟通:

快速
发帖

客服
热线


7*24小时客服服务热线

关注
微信

关注微信二维码
顶部
查看: 425|回复: 0

4399游戏盒最新算法讲解

[复制链接]

1049

主题

1121

帖子

3万

积分

管理员

Rank: 9Rank: 9Rank: 9

金币
9845
巨币
8185
积分
37899
发表于 2019-10-25 18:46:42 | 显示全部楼层 |阅读模式
第一次发教程 出现问题请见谅
5 J6 C  w- {( q' g% Y这次是最新版本的4399游戏盒登陆密码加密讲解和两个sign的讲解  
* y0 r# E7 j( E/ C% D. |- Z# k  g
由于我测试的时候是无法对这个APP进行IDA调试的 所以就静态分析了一下, S2 I9 n- X3 R7 P" c
# W4 M" j" O. r/ d! D! \8 b6 L" U
1 y! M+ ?* f5 a
  1. POST https://mapi.4399api.net/user/box/android/v1.0/log-in.html HTTP/1.1& R- b8 k. j* F( g1 l7 m8 y3 P
  2. User-Agent: 4399GameCenter/5.2.0.39 (android;Nexus 6P;6.0;1440x2392;WIFI;1376.416;yaoqing)
    % T! x7 o1 Z3 L
  3. mareacode: 350100- d* B) Q' W0 i* [  b7 J
  4. a-id: decd74ca59799d58
    * }# b( l$ [% e  l& m
  5. e-id: 867981022896164
    ; p2 z) e7 D3 r7 X6 G! ]: W
  6. m-id: D4%3A61%3A4E%3A13%3A10%3A1F3 J; {, M- Z* \$ H9 F; p/ t- @8 M
  7. s-id:! u6 @  [9 d5 }
  8. mauth:
    ! Z5 [( T0 r; H
  9. mudid: 1085glt3vuUywD5g808eZb67a
    2 p+ s7 W& v9 ?% }5 }7 ?" Y
  10. pauth:5 D# S% C$ ^, Y5 M1 M0 ?: w' ?
  11. SM-DEVICEID: 2019101514035076086dc3e7e2dc00afe0043881a46e18018036cbcdd51ca5
    $ i- L; W1 e, }+ m
  12. mdeviceId: 867981022896164
      b$ L# B. ^- Z* k% |7 u
  13. mauthcode:
    7 \5 o+ F! C1 R  W  R. {8 a- I
  14. Content-Type: application/x-www-form-urlencoded
    3 Y5 X/ P( g; D6 P3 w, a
  15. Content-Length: 161
    % q1 \- n& ]" i. c, O
  16. Host: mapi.4399api.net- }  X7 o8 n1 z7 H/ B; L
  17. Connection: Keep-Alive
    9 p% ?- A: L3 p% T, H3 C% r/ ]7 {9 c
  18. Accept-Encoding: gzip# T  Z5 X8 y$ g* p( q
  19. password=JE%2FYTsyiLwE%3D&deviceIdentifier=867981022896164&dateline=1571863440&sign=c80c8c800fa61cccc02e12e87da33620&model=Nexus%206P&username=13665098754&info=1
复制代码
这是抓到的登陆包
2 g: m, u% Z1 x9 z; V3 k. F大概能看到两个参数需要处理 一个password 一个sign- a1 U; D( D- J( p5 j

8 d' B1 X5 X5 G' j反编译4 {: c: Y/ t4 e$ I& b5 Q+ F3 i# G
" O/ K/ Z# ?+ i; m+ ~/ ^
找到关键点
) G0 {7 u4 E5 y% B# u; @
7 w! b; I+ Y3 d1 ~跟进以后就是Native函数了 这里我们从名字就能大概知道password是一个DESCBC类型的加密(不排除重写) 我们也只是猜测
6 `1 Q6 Y& F1 N2 K) a- Y# D. {5 L3 y
: e: S$ {3 ~7 e/ {1 O: Z* `# Z
1 [: A: q  ?6 N+ i. a
  1. public class AppNativeHelper {; w8 f4 s8 a: p0 `$ }
  2. static {: ^+ o7 X0 J4 c' ]# ]1 _) T
  3. try {
    * l/ x4 ^: @: [/ S  c
  4. SoFix.loadLibrary (BaseApplication.getApplication (), "m4399");
    ; C; `) `3 y# }2 T& f- p5 P. ?3 t
  5. Log.d ("AppNativeHelper", "load libm4399.so");1 Z# W! y- l! j$ \
  6. }
    " q5 Y& D* w- V$ b% a, G/ l
  7. catch (SoLoadFailureException v0) {
    ! z( T2 Z& _# A7 ^0 V0 X
  8. v0.printStackTrace ();
    ' z# e6 H4 C2 E2 l2 h% I
  9. }4 f0 [5 @) J/ _# V
  10. }
    ; M& t% c4 J( ?7 o( x( ~9 l' R2 r
  11. public AppNativeHelper () {
    % x: R  d& I4 O
  12. super ();. \7 J7 J; S) o0 p. P# N
  13. }" U1 |6 P. w7 ]7 L
  14. public static native int applyPatch (String arg0, String arg1, String arg2) {
    * z: A+ Z! Q8 C8 j2 x  K7 ?3 B
  15. }( T; {) s+ J6 \# _4 O: m
  16. public static native int delayRestartProcess (String arg0, String arg1, long arg2) {
    3 c6 O. Y9 A( y* I" p: D
  17. }
    1 e* s+ x$ F# n' r' d* O" T) ~6 O& m
  18. public static final native String desCbcDecrypt (String arg0) {
    , h; s1 b  Y/ [$ {# l4 _
  19. }- u- Z- J9 R( F& y, r" v# T
  20. public static final native String desCbcEncrypt (String arg0) {
    4 u# M6 B0 ]( T
  21. }
复制代码
拿出libm4399.so拖进IDA进行处理  ) R  I/ _1 n' [# m

" }4 q2 B: h4 q5 u9 _这个So是动态注册函数/ _6 w- \9 y1 d  m5 N) Y

/ R" b' A0 }  u所以我们进入Jni_onload 导入头文件 找到RegisterNatives函数
$ M3 O9 V; @) c; DRegisterNatives中第三个参数就是我们注册Java函数的实际地址8 }0 B: z6 ?6 `8 p; ~+ Z  N9 F
; n. h. |& a: ]2 I  G: ~
3 A$ N' y7 t) S" W
6 f' W# u" s! l( I
进去以后是DCD格式的 第一项是函数名 第二项好像是格式还是啥 重要的是第三项 这就是我们的函数地址了 找到我们要的函数 然后找到函数地址: q! b0 M1 Z( W
4 D* j5 `* J: F% A
5 U' Z5 D% T7 O9 W" u0 D+ d; e* [
然后进来这个函数
2 c% L: g  u1 F+ r6 i/ [' j, y  d  Y; m: T# V; M* q+ t# f/ I

7 B: D) x7 z6 D2 N
  1. int __fastcall sub_17024(int a1, int a2)% {: p2 \! W* ~5 w8 H' N2 W' L* B
  2. {
    7 f( k. p& a. p6 K! v" H
  3.   int v2; // r4
    1 I0 }+ I: O+ `
  4.   int v3; // r5
    6 @% `) J8 x% O0 e
  5.   char *v4; // r6: n. L% i+ r/ V, `% x5 a
  6.   int v5; // r0
    : d4 g1 j: N3 }$ J
  7.   int v6; // r3
    . G6 s# E; K! A& p% L6 s" q" L4 i
  8.   char v7; // r2( n* U5 H, n; q8 }5 c; o
  9.   int v8; // r4
    * `8 `' w: w+ }& Y1 z! z

  10. - R7 S9 @* J' [% B
  11.   v2 = a2;' A" m% Z" z$ ]2 a/ K  R5 _- N- I
  12.   v3 = a1;
    - t2 a" Y! y; Z+ [* [
  13.   v4 = sub_17274(9, 1);
    ! L& i) L# `2 d1 W5 Y7 t0 U
  14.   v5 = 0;
    - H) o: c5 [" H# X; D
  15.   do
    3 Z- ], P' K6 {
  16.   {
    , \/ y3 M+ ]# T6 l0 o) N
  17.     v6 = (dword_1B040[-v5] + 101) >> 15;. f6 y" K8 x5 B+ l: U" E
  18.     v7 = v6 ^ 151;6 a# V% n  K! k
  19.     if ( v6 >= 102 )
    : h$ ^5 p' c% p. Z# x8 \' i
  20.       v7 = v6;
    7 u( G* c0 y- V3 {  B
  21.     v4[-v5--] = v7;: u' H" t# U; r3 c) @
  22.   }( t1 s+ k$ p5 l$ ]' Z
  23.   while ( v5 != -8 );                           // 循环8次 获取DESkey
    1 W# R! \$ ]/ C; N, c+ m% W
  24.   v8 = sub_64B8(v3, v2, v4);                    // //进入加密函数
    , _6 t% J1 q7 T* |' I
  25.   sub_17284(v4);
    3 b$ ?; c( H* j# z, x9 G9 Y$ K0 N% U
  26.   return v8;0 m0 n. J- M" m" d* e8 b% j; Z
  27. }
复制代码

9 {1 `/ v/ X, `2 x/ u  s/ f- {/ ]9 X& A* Z" @& p
通过前前后后的分析 这里就是获取Key的重要地方了 从一个地址里面取值出来 然后循环处理8次 然后我们进入dword_1B040看% r- _, t, c3 n
$ }' i1 [+ w: b% j8 w( n% B

; g3 `7 i/ P) b+ q3 v
4 Y( K# g' m- Y) `$ Q' {1 A) O- {6 N# w8 d% `5 j
看不出什么猫腻 我们转换一下格式 先转Double再转为array IDA右键就有
9 }5 e1 U& ~1 a+ H
( @' c: A2 x: O
' _3 p1 N) _7 v

8 Q- U# c& u  v, N6 h1 Q9 Z
2 v; T1 M. c1 F& y+ R+ @然后我用js翻译了这小段so逻辑理清楚后一下子就明白了
& A' Q% C9 r5 V6 y1 A+ w" H7 n
6 O1 [5 K. K, g2 C
3 X5 t8 [( q* @' l4 R
  1. function get(a) {
    5 r2 ~- S5 q+ A; c$ J$ y3 s4 j
  2.     v6 = (a + 101) >> 15;& B7 |+ H( k. Y7 k. e2 u& r4 [
  3.     v7 = v6 ^ 151;; V* [- K/ {# w* U# ~0 R
  4.     if (v6 >= 102) {- M+ e5 }' F. D1 Y3 P
  5.         v7 = v6;( u+ l" p+ ~$ G% x2 z7 Z2 J
  6.     }
    ! N" G+ v' L( F
  7.     return v7: d1 P, I3 _* b/ O, s% b
  8. }% D3 S! ~  U2 A4 u- |  W1 {+ t
  9. function a() {( ^7 k1 N3 q( m: i( ^0 `
  10.     arr = [0x3A7F9B, 0xFFDAFF9B, 0x3EFF9B, 0xFFD9FF9B, 0xFFCFFF9B, 0xFFEB7F9B, 0x3B7F9B, 0xFFD37F9B];3 z* Q  s( }2 o% D9 ~- |
  11.     var aa = new Array();
    * n' b" e& G7 _' p$ k% q" O# D9 h) h
  12.     for (var i = 0; i < 8; i++) {
    4 E/ u& T" x8 b" q+ h6 z
  13.         aa.push(get(arr[i]))
    ( l, ]+ Z' ^; Q5 T2 H/ j! v" S0 L
  14.     }, }# U3 L3 k& P, N. N; d
  15.     return aa6 A/ S: q$ D4 F/ @; r4 U
  16. }
复制代码
# P. u* t+ r  b

% k) s4 W4 c3 v. Y# n这里返回的就应该是key数组了 {117,-223,126,-221,-201,-192,119,-208}
& Z$ Q7 x! r3 n然后转换到易语言的字节集就是{117,33,126,35,55,64,119,48}文本为u!~#7@w0 (这里的转换就是由于其他语言的byte取值范围 -128~ 127) 易语言好像没上限 所以我们只需要把-的给他加上256就能变成易语言的字节集了), d8 {5 ^0 n/ I# X% {! I8 p
* I" _( }& D0 z5 s/ g
到这一步我们已经拿到了KEY了7 f0 ]) _$ u; k# ^$ c

9 _4 t! a8 r' L1 J现在就差一步IV了: X9 o4 K1 v$ x% e0 y
& b% |% Z+ F& v; {9 }( g
前面一直没说) m# {6 u' O! s( j6 ^

) _$ F. C# P0 _$ U因为这个so函数名全是匿名的 所以在分析的时候很难去判断这个函数到底是干嘛的 这种so分析起来就需要自己花点时间和结合经验来操作了
/ m/ ^3 c4 }/ E: R  O' ?
$ e! ]9 L/ i2 S/ v这里我都给大家分析完了" B) v- j  I# J* G( h

: T" M8 N- ~( y7 C) L& K, U; F

3 }3 _. J" b1 _4 @0 }0 M3 ^4 [, [6 E7 K# `, q( Z/ |% i, R. `% y9 G

5 R3 m8 Q- i7 a
0 s) Q: C4 e" X" \我们已经找到了最关键的加密点了 而且我们现在key也有了 只差IV了" l3 J( h+ M- x  Q6 ?

& b1 ?( j* U/ u# u* Wsub_4720这个匿名函数其实就是DES_cbc_encrypt
/ g: f: C( l( t0 b" J
  D* h1 W+ H1 z; r$ Svoid DES_ncbc_encrypt(const unsigned char *input,unsigned char *output,# h5 ]2 u2 L# s; g  j* t
              long length,DES_key_schedule *schedule,DES_cblock *ivec,+ H9 A6 {8 p9 Q* ^. p3 d! ^
              int enc);
, f' o# b3 I! H. O( S- ]$ @" e6 z
$ b7 `, d# P5 R1 L. T: U$ n- j2 ]0 x这是DES_cbc_encrypt参数的定义1 j. _! o8 \4 _0 {: d

7 |& U* L5 H: v  y依次是输入流 输出流 长度 key iv flag/ y! p/ ^! Z/ G' W0 x/ V* o

$ P  }% |+ P6 s恰好能 对应上我们的函数 所以 iv应该就是我们&v11所指向的值了1 R( n) ?: a( w2 ]

" D( W3 u" w- X! R

9 u; L/ j8 O( z5 f3 }8 k3 v+ q
  1. .text:00006618 ; 20:   v12 = 0xEFCDAB90;
    ( O, K* S" O9 k9 C; P0 {& f' H
  2. .text:00006618                 LDR     R0, =0xEFCDAB902 T# W8 K  O$ [. \& F6 e
  3. .text:0000661A                 STR     R0, [SP,#0xB0+var_9C]5 }. ~% y/ U; E) w
  4. .text:0000661C ; 21:   v11 = 0x78563412;
    $ ^) d/ a" T  Y. s0 x7 W
  5. .text:0000661C                 LDR     R0, =0x78563412
    2 }# k  e8 H! x! a* G0 V4 b
  6. .text:0000661E                 STR     R0, [SP,#0xB0+var_A0]
复制代码
这里V11在我们的伪C代码中只赋值了0x78563412  但在汇编里面他实际是赋值了0xEFCDAB90 和0x78563412的 所以我们的iv应该就是0x1234567890ABCDEF
+ X6 a6 S  M9 w1 I; x, v# G6 q6 C" @" T5 e6 d# W) j& P: G; S
在我们运行的时候 取值事从后往前取得 两个一组 这个我确实也不太明白具体原因 也是在无名侠前辈哪里学得 也就是 EF CD AB 90 78 56 34 12 这样来拼接得! X* w- i) x" \
3 D: A6 R9 `! u9 K/ k
好了 现在我们key iv都有了 我们在不排除有变异得情况下可以来测试一下能不能解开密文5 a8 {( S3 ~* ^5 P

; P0 |1 f% I2 v$ y* R/ o0 A

7 k# u, ^6 y$ @4 D* Q+ ~9 \
5 b1 t6 x8 ~4 }- x( t  m0 H; ?. O6 s& t1 I
成功解开
  E( @6 K- @. m* \
# Q/ z. M& w$ R3 e6 m这次so分析得难点其实就在于无法动态调试获取key或者IV 每一步逻辑都需要自己去看
# T% R6 F, ^& B6 L0 g6 F其次就是全是匿名函数 需要自己花点时间去查看每个函数的功能
' X; s+ Z5 b& [" q
+ L7 M/ j; A! ?0 B9 \但总统上还是不算难得 只是需要慢慢琢磨一下得! f' w* _' E7 n2 s  K9 h
! `3 [! `0 ]% H5 ?, \" ?3 q
实在是太累了 如果大家对登陆得sign和签到得sign有想法我下次再给大家写文章把( D9 V6 v; K+ Q- J1 G

% S3 r2 M0 W. S3 R6 G

/ U" A8 N) \7 X5 P- g6 {; ]1 t4 \2 k" G( X) B
$ Y9 A. ^9 k$ s1 F; X

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
爱内涵论坛关注易语言与按键精灵的脚本辅助软件开发领域。                     VIP视频目录            VIP会员介绍            联系客服加入会员            爱内涵免费①群            爱内涵免费②群            爱内涵免费③群            自助加入会员
回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【加入会员,永久免费学习】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|爱内涵易语言 ( 浙ICP备19016710号-3 )

|网站地图

GMT+8, 2021-3-5 08:05 , Processed in 0.092874 second(s), 12 queries , Gzip On, File On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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