爱内涵易语言论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

快捷登录

在线
客服

支付故障请联系客服服务时间: 9:00-24:00

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

快速
发帖

客服
热线


7*24小时客服服务热线

关注
微信

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

4399游戏盒最新算法讲解

[复制链接]

1762

主题

1848

帖子

3万

积分

管理员

Rank: 9Rank: 9Rank: 9

金币
9845
巨币
11680
积分
39499
发表于 2019-10-25 18:46:42 | 显示全部楼层 |阅读模式
第一次发教程 出现问题请见谅
, H5 l1 L: ^0 M3 {3 I" E这次是最新版本的4399游戏盒登陆密码加密讲解和两个sign的讲解  
4 ^3 V. Q  X% {, H9 o2 Q4 z; \. \
由于我测试的时候是无法对这个APP进行IDA调试的 所以就静态分析了一下4 y. s$ ~0 m' t/ c; N6 x
3 `- ^1 D) L' t  @( }) R

  ?  E/ w4 p3 J7 x! D3 u# q6 F
  1. POST https://mapi.4399api.net/user/box/android/v1.0/log-in.html HTTP/1.1
    ! o8 O' k8 j( X, J$ \9 l0 Y2 C$ F( l5 }
  2. User-Agent: 4399GameCenter/5.2.0.39 (android;Nexus 6P;6.0;1440x2392;WIFI;1376.416;yaoqing)& k* A0 r( \( L& G' Q/ c
  3. mareacode: 3501001 V0 W; s# o* @% Z9 p, M9 E
  4. a-id: decd74ca59799d58, P% m8 }: N) i3 l; u( M
  5. e-id: 867981022896164. Z  c6 |. o1 b, c4 h
  6. m-id: D4%3A61%3A4E%3A13%3A10%3A1F% m2 R0 }4 {6 \3 P
  7. s-id:4 ], }* [) [  U2 a  L* J( s
  8. mauth:
    0 H2 h8 k, c3 H/ J' j5 J* U
  9. mudid: 1085glt3vuUywD5g808eZb67a& [) }9 `2 @. L* u0 e
  10. pauth:
    ) O1 W: E! O5 D# ?( r/ Y/ B; j
  11. SM-DEVICEID: 2019101514035076086dc3e7e2dc00afe0043881a46e18018036cbcdd51ca5* @/ _- b: U  N
  12. mdeviceId: 8679810228961648 J/ O3 D; t  A8 \) [
  13. mauthcode:  b- H# f6 l4 o! P! `
  14. Content-Type: application/x-www-form-urlencoded
    * @) q) k7 u2 B% B4 B/ x/ j9 k
  15. Content-Length: 161/ t9 p' Z! G/ K) M% [
  16. Host: mapi.4399api.net. s; u' X% `5 r( u
  17. Connection: Keep-Alive
    - q9 m  z( |! f. q5 g
  18. Accept-Encoding: gzip. c+ l. @0 f: t+ [. T7 O; v
  19. password=JE%2FYTsyiLwE%3D&deviceIdentifier=867981022896164&dateline=1571863440&sign=c80c8c800fa61cccc02e12e87da33620&model=Nexus%206P&username=13665098754&info=1
复制代码
这是抓到的登陆包
7 q! Z" H7 X$ }' P. f大概能看到两个参数需要处理 一个password 一个sign8 v) e- x3 P4 n6 A# `" ^
# y9 Q! w( C5 g0 v$ g, y% o
反编译
3 w" B! Z, [) G+ A
1 ]# i! w+ g* J  L# I  I+ g找到关键点+ T5 {/ h% ^3 P$ _6 D) s

* {) Y4 r5 ^9 V; {, i/ h1 u1 c跟进以后就是Native函数了 这里我们从名字就能大概知道password是一个DESCBC类型的加密(不排除重写) 我们也只是猜测6 f, j+ R, B$ p3 M. ^
3 z& _, f$ N5 u: v6 B9 m' i  V

: v; _) ]7 ~2 z" g; q6 x9 a
  1. public class AppNativeHelper {' S! k1 h2 {/ \0 V* z3 {4 [8 D6 Q  @: [
  2. static {4 ^/ O7 X3 A* m5 J# ]- ?
  3. try {# h" B! {- d/ r! m% z3 v7 @
  4. SoFix.loadLibrary (BaseApplication.getApplication (), "m4399");
    , E+ {% T. b; D
  5. Log.d ("AppNativeHelper", "load libm4399.so");7 T0 w" Q5 q  d" @* n3 X
  6. }
    8 g: |$ U* W/ U8 t* [, L. V
  7. catch (SoLoadFailureException v0) {
    ) X. R: H! e5 w% c& ~" {  |& W/ ?
  8. v0.printStackTrace ();
    3 T- N. q/ |, V
  9. }6 ^: \5 a1 J7 A$ w
  10. }8 V  @' e" r, x1 ?% ]7 r
  11. public AppNativeHelper () {
    ; L' d; a* m8 Y, ?. e
  12. super ();
    / b! l. z9 Q, N2 c" a
  13. }
    ) j# G+ J, Y$ M
  14. public static native int applyPatch (String arg0, String arg1, String arg2) {2 f! y% h4 ~. ?  x7 {& w2 X6 z
  15. }
    3 F4 q/ x) F- d
  16. public static native int delayRestartProcess (String arg0, String arg1, long arg2) {
    " ?) s9 J6 U, S* X
  17. }
    4 r7 N$ B5 f6 Y: K7 H! ^8 u
  18. public static final native String desCbcDecrypt (String arg0) {
    0 t# X5 D# Z  N6 _
  19. }; W2 ], k# d" q, R7 A
  20. public static final native String desCbcEncrypt (String arg0) {
    / |* S6 j9 \; k" E5 V& V) E" Q" j
  21. }
复制代码
拿出libm4399.so拖进IDA进行处理  
1 V& j3 k. B: `. G
2 y3 X# k- C' ~  n' l/ U这个So是动态注册函数3 |3 [- I. p4 b- c2 v9 y- k
( t- _7 e2 k* Z- W2 L
所以我们进入Jni_onload 导入头文件 找到RegisterNatives函数
8 {; m) [/ ?  M* N! ^- g+ m$ cRegisterNatives中第三个参数就是我们注册Java函数的实际地址
- U7 G& W3 N. F9 U, b4 P; Z3 P2 u# E: w2 L% o% ]4 M- `7 N
9 }5 y, o- U2 @) i  [0 z; r
: z; M! z/ d; A" s
进去以后是DCD格式的 第一项是函数名 第二项好像是格式还是啥 重要的是第三项 这就是我们的函数地址了 找到我们要的函数 然后找到函数地址
, e5 e4 O: T$ i) J2 g6 b/ A" i# `( {; K5 K8 B& w8 D9 G
" U6 V5 ]) T$ Q
然后进来这个函数4 n; n5 u" F% J. n; |$ H

" Z0 P) M$ J$ r# X2 j- M

8 P+ P+ E, _$ h2 w& U5 z
  1. int __fastcall sub_17024(int a1, int a2)
    ) m0 S% @3 L: Q# p  [# [5 [, T" b
  2. {
    5 I( Q( V  ~+ `. }, w# d5 f" k3 m
  3.   int v2; // r4, H: }; D% g: q3 B0 o% d
  4.   int v3; // r5& |3 A& L6 `( {$ o# ]) r$ `
  5.   char *v4; // r6$ p" m4 T8 {3 i4 v
  6.   int v5; // r0
    " E% N$ i; G; S
  7.   int v6; // r3
    / P, F0 n# O8 h8 a
  8.   char v7; // r2
    ( ?& Q9 V* A$ j1 v( H
  9.   int v8; // r43 l5 @8 ^, V6 `8 {
  10. 4 S$ N3 }- h- n( ~* q' ^& R/ @
  11.   v2 = a2;
    ( \8 F8 ^% u: M2 ^( {- w
  12.   v3 = a1;
    3 y* g! ?  }5 V+ O2 T
  13.   v4 = sub_17274(9, 1);
    2 t: W6 j! s; s# Q# ?
  14.   v5 = 0;; j7 T- X5 g. o/ ?- z. J
  15.   do& \/ P7 I6 m/ @& i8 V* U
  16.   {7 H& C6 O5 F& p) r9 h) s
  17.     v6 = (dword_1B040[-v5] + 101) >> 15;; w. T0 s1 K% z0 ?( G5 q7 Z
  18.     v7 = v6 ^ 151;
    2 m) _, i& }/ l, [0 x0 [
  19.     if ( v6 >= 102 )5 N8 M$ L2 z! _
  20.       v7 = v6;
    : s0 j' ^- Q% x( O
  21.     v4[-v5--] = v7;8 |7 t& F9 o7 v0 @$ N; X
  22.   }( J( t3 r, g- R  v3 j3 A
  23.   while ( v5 != -8 );                           // 循环8次 获取DESkey+ |, p. Z+ y, b* V
  24.   v8 = sub_64B8(v3, v2, v4);                    // //进入加密函数2 o" k& l# u3 f
  25.   sub_17284(v4);
    $ x3 a0 M/ L1 e& _
  26.   return v8;% P8 N2 L% V, P) t: ~! E& z+ {
  27. }
复制代码
4 f6 d8 i. j% Q2 y' Y& g
: t; D2 U. u* I5 \8 f2 p
通过前前后后的分析 这里就是获取Key的重要地方了 从一个地址里面取值出来 然后循环处理8次 然后我们进入dword_1B040看3 r# V! i! [4 m( |  u

: B0 }7 F1 S0 f& c

5 J, P6 {4 s* k) n
; N0 {% s% {( n9 K+ X
1 j, O+ S0 a9 {) w! r. e看不出什么猫腻 我们转换一下格式 先转Double再转为array IDA右键就有
# g8 f" w  l% a. [  h: M! w& c1 Y0 P" C; p- n$ s3 B0 Z( W9 p

% e5 z/ |5 `+ q3 I$ }5 c+ h. p/ R! Y& j
7 {* |' F  I/ r' I9 C
然后我用js翻译了这小段so逻辑理清楚后一下子就明白了5 T1 t7 R' B% D

! T' J) A& T+ L# q

2 u4 j4 Y2 `+ t, e. T! B8 w
  1. function get(a) {3 a) Y5 m+ |* S8 d* }
  2.     v6 = (a + 101) >> 15;. ]! m" ?/ D0 Z' C9 k
  3.     v7 = v6 ^ 151;
    " b9 F$ f( t, t: b
  4.     if (v6 >= 102) {' r1 r' C4 I! ^% J5 {
  5.         v7 = v6;& m$ b9 }* \  u
  6.     }. i0 c# o1 q" a9 z/ ?
  7.     return v7+ Q0 \. C) p( B. c6 l  ]; s
  8. }
    , n- d' o- M  e' Y- t
  9. function a() {
    / |  [9 H5 w! ~4 ]6 @5 S
  10.     arr = [0x3A7F9B, 0xFFDAFF9B, 0x3EFF9B, 0xFFD9FF9B, 0xFFCFFF9B, 0xFFEB7F9B, 0x3B7F9B, 0xFFD37F9B];
    ; X) g, c+ g1 k) O
  11.     var aa = new Array();' U% \! x  U$ g7 f' [! ?6 u- k6 ?
  12.     for (var i = 0; i < 8; i++) {! R: |7 q) ]8 d" O% ^1 g/ S
  13.         aa.push(get(arr[i]))
    ! S3 C/ H* l4 f, A
  14.     }; Y4 t$ D5 }! X/ g9 b/ [: J
  15.     return aa6 G9 B) ~8 p8 {9 v. K
  16. }
复制代码
4 e5 }! s0 A4 Z" j4 m

" e, I, w" V) g0 y& c这里返回的就应该是key数组了 {117,-223,126,-221,-201,-192,119,-208}
4 y# b8 L7 x6 D. A8 Q9 S然后转换到易语言的字节集就是{117,33,126,35,55,64,119,48}文本为u!~#7@w0 (这里的转换就是由于其他语言的byte取值范围 -128~ 127) 易语言好像没上限 所以我们只需要把-的给他加上256就能变成易语言的字节集了)6 H' ^! S0 V' M1 z

) h' L" [" l- M/ i" L* ?' o! ]0 F到这一步我们已经拿到了KEY了% z. `1 u$ v9 J. T. j
9 Y, B* f3 Y' s# G
现在就差一步IV了
, O3 U, W2 \8 ^4 }
. F( e5 E! T& o1 R前面一直没说
# f: J5 ~7 C. G2 F5 n5 }
- a% s2 ~, V0 B" C- Y( [% y# _因为这个so函数名全是匿名的 所以在分析的时候很难去判断这个函数到底是干嘛的 这种so分析起来就需要自己花点时间和结合经验来操作了
: P9 `" C0 [% p$ ~8 }1 A& L& W, F$ V& q& T6 f* e7 Q
这里我都给大家分析完了
$ z7 X# b( |  Z3 z6 k3 L2 A6 C3 T* k! M9 L0 M& T$ [6 }

/ h2 i& V) p" m5 F2 w/ W1 s+ `; E  ]- ], q

, {9 `0 o% G1 ^6 `& O9 ~. k0 ^6 J/ X( U4 b7 |& r: \/ ?
我们已经找到了最关键的加密点了 而且我们现在key也有了 只差IV了
/ O: Y# Y: s3 B3 D: y, l8 T- e4 T( e
/ E# h% v: H, |5 A" O+ B" ?sub_4720这个匿名函数其实就是DES_cbc_encrypt
: _  A) G: R" H9 _# L- B+ r
, a2 j3 |% U) P# E; d' J+ Bvoid DES_ncbc_encrypt(const unsigned char *input,unsigned char *output,
/ z" I( M6 l, V) T0 o$ j' a              long length,DES_key_schedule *schedule,DES_cblock *ivec,$ N# |* l! ~# O9 K3 Z! m
              int enc);' m6 I+ o! U6 e2 W$ L

1 Q2 I0 S1 d/ a' f6 C9 d5 C; N这是DES_cbc_encrypt参数的定义
4 k' ~/ M6 d1 x7 }4 `
7 G% \( G7 J* \4 O2 j依次是输入流 输出流 长度 key iv flag
; ~: \3 O$ l# }. b- k( V" i! S% j/ E* d! y* H: ?! w! w( ]* j  @
恰好能 对应上我们的函数 所以 iv应该就是我们&v11所指向的值了. o6 [) j% S" K+ I" z

, r9 k3 P. X& J6 _5 N2 a

) k* k9 m7 U6 ^; A" o! S
  1. .text:00006618 ; 20:   v12 = 0xEFCDAB90;
    + f: q" F* ]1 f0 L! O
  2. .text:00006618                 LDR     R0, =0xEFCDAB909 k7 a' L  S& R  Z/ s( I
  3. .text:0000661A                 STR     R0, [SP,#0xB0+var_9C]
    - N6 ~7 ]$ L, q- l
  4. .text:0000661C ; 21:   v11 = 0x78563412;" Y! m% G$ R. K% J
  5. .text:0000661C                 LDR     R0, =0x78563412
    5 f( v& a4 _0 [& n8 w1 t0 f
  6. .text:0000661E                 STR     R0, [SP,#0xB0+var_A0]
复制代码
这里V11在我们的伪C代码中只赋值了0x78563412  但在汇编里面他实际是赋值了0xEFCDAB90 和0x78563412的 所以我们的iv应该就是0x1234567890ABCDEF
; D( a. X& J2 \% M; z
8 {( R8 M* {3 o6 c; o$ r6 O8 Z在我们运行的时候 取值事从后往前取得 两个一组 这个我确实也不太明白具体原因 也是在无名侠前辈哪里学得 也就是 EF CD AB 90 78 56 34 12 这样来拼接得
5 H8 U4 g. L+ S; M) }; [( G9 s& I* L3 `3 N3 C; |4 i; F& l0 f  H6 D
好了 现在我们key iv都有了 我们在不排除有变异得情况下可以来测试一下能不能解开密文. V' K' p2 x4 y
+ h4 _# p7 u4 C1 m
* _; m6 w8 e" D2 W& z& M- x
8 s  H( _. Z' n# ]2 T& p
8 B6 ?- j6 @$ i! c& V  b* t) m) y
成功解开7 l6 V6 [* v9 l1 n6 N- X
" }. d  H# J  A* S3 h
这次so分析得难点其实就在于无法动态调试获取key或者IV 每一步逻辑都需要自己去看# M0 G) U% x* K1 G- _- G
其次就是全是匿名函数 需要自己花点时间去查看每个函数的功能/ {; ]5 z& `" ^& N

% j% ~6 Q9 h2 w8 N$ }* T& f  I& R但总统上还是不算难得 只是需要慢慢琢磨一下得
- G/ f( S. a9 p3 [5 D/ A  M) ?6 h* I" U6 h
实在是太累了 如果大家对登陆得sign和签到得sign有想法我下次再给大家写文章把
3 |4 y  l1 k8 \) m8 w  t. x/ c% t* q3 X* i9 {) H
& h& O' X" B, @2 @6 y

6 \+ s% g. u. j( ]! g
+ D( L5 u- V  C

本帖子中包含更多资源

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

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2021-9-24 01:55 , Processed in 0.066524 second(s), 22 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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