看雪学院 前天 19:39
某App参数加密分析:X-Gorgon参数生成过程解析
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文详细解析了某App(版本4063)X-Gorgon参数的生成过程。通过unidbg进行hook和日志分析,结合IDA Pro进行逆向,逐步定位了加密逻辑。研究发现,加密过程借鉴了RC4算法的思路,涉及S盒(v78)的初始化和对输入数据(v54)的加密变换。关键在于理解v54、v78以及辅助key(v87)之间的相互作用,并分析了其中复杂的位运算和逻辑混淆,最终实现了X-Gorgon参数的生成。

🔍 **X-Gorgon参数生成流程梳理**:文章通过unidbg的hook与日志记录,结合IDA Pro的静态分析,详细追踪了X-Gorgon参数的生成代码路径。首先固定时间戳以保证结果一致性,然后通过hook memcpy等函数辅助定位关键代码段,逐步分析参数的生成过程。

🔄 **RC4变种加密机制解析**:研究发现,X-Gorgon参数的生成核心逻辑类似于RC4算法。其中,v78被用作S盒(S-box),通过一个包含固定字节和动态变化的key(v87,其变化字节与Gorgon结果的第三、四字节相关)进行初始化。随后,利用这个初始化的S盒对输入数据v54进行加密变换,实现了类似RC4的密钥流生成和数据加密。

🧩 **复杂位运算与混淆技术分析**:加密过程中运用了大量的位运算(如提取高低四位、异或、逻辑左移/右移、按位与/或/非)以及复杂的逻辑混淆,旨在增加逆向分析的难度。例如,对输入字节的高低四位进行置换,以及通过一系列数学运算和分支判断来扰乱数据流,这些都是为了保护其加密算法的安全性。

🔑 **关键数据流与变量追踪**:文章重点分析了v54(加密数据)、v78(S盒)、v87(Key)这三个核心变量的来源和变换过程。通过对trace日志和IDA反编译代码的细致比对,揭示了v54的初始值来源、v78的初始化方式,以及v87中两个动态字节与加密结果的关联,最终构建了完整的参数生成模型。

git_21210wzzzh 2025-10-21 18:08 上海

看雪论坛作者ID:git_21210wzzzh2025

gorgon

okay,现在重回正题,该样本app版本为4063,具体的unidbg补环境比较简单,就不提了,定位参数生成位置和寻找入参可以参考果冻爽大佬的文章https://bbs.kanxue.com/thread-285623.htm。

由于加密会用到时间戳,所以先把时间戳给固定了,保持多次踹死结果一致。

开始前先踹死一份日志,后续主要根据日志+unidbg hook+ida进行分析,trace的时候可以顺便把memcpy也给hook上,这样方便后续分析。

X-Argus
Xt2BxcP5LV9DAYS7/t3toblfa8SbPeWKHNNQ0EuwOQq0tOW4TFE7htQ7fZ9WGyngoYDkosb7p1eXgg4ed4H5nVJlmwpUoFhGzo3w40uzWQju0iKkve/mueX0bV+mFba+taAO5tqvgxi79bJPegIClUC/Wv8lOMCmRjkxQj5N94/m8PziZ4zkej1wsUgoRrulpiWmG0th+TuMiahA6lSPGZaEdoPYugmUZDSldBEUEk3Io4CPr2ZLmD3RuYDmUK79eottaSXLajZOi80sQ0+NHhmnnHBkjAQQC7DmhWF12jSm3jMlVDtn0HUJUneT4Fo/Yp8=
X-Gorgon
8404e0ad00009058bdc1a1c16365352e6593aed16a8fc7100f68
X-Khronos
1752473458
X-Ladon
sAIHSCUjZK9ZOp/dqwzMB47c0K4L1eW+U1UDkhpurWKB5gIp

这是unidbg跑出来的结果,其中的x-gorgon是要分析的内容,大小为26字节。

使用010editor打开trace日志,随便搜一下结果中的前几个字符串。

直接就搜到了,hook memcpy的好处也体现出来了。

直接向上搜这个地址:

可以看到,是在这个地方写入的0x38

来源于上面的0x12618ac0这个地址,继续向上找这个

str(.*?)0x12618ac0  直接用正则表达式搜索会快一点

找到了,是在这个地方

继续向上跟,这里就不带着跟了,只给出找到的相关trace日志。

0x1209c1f8: "ldrb w8, [x8, x21]" x8=0x1261ade0 x21=0x0 => w8=0x84
0x1209c1fc: "lsr x8, x8, #4" x8=0x84 => x8=0x8
0x1209c200: "ldrb w1, [x9, x8]" x9=0x12189f35 x8=0x8 => w1=0x38
0x121702b0: "mov w20, w1" w1=0x38 => w20=0x38
0x121702e8: "strb w20, [x8, x21]" w20=0x38 x8=0x12618ac0 x21=0x0 => w20=0x38

这是跟0x38所有的相关日志,最上面是g结果中的第一个字节,第一个字节提取高位之后从0x12189f35+0x8提取出了0x38,0x12189f35再向上找就找不到了,考虑是ida中的常量区,打开ida跳转过去。

0x12189f35+0x8 的位置不就是8吗,这根0x38有什么关系,有的兄弟有的,0x38是8的16进制的形式,在继续观察0x38 0x34 0x30 0x34....之后发现这一步其实是将结果中84...高、低四位转换为16进制形式表示,所以结果在上面就已经生成了,需要继续向上看。

0x1261ade0这是0x84的地址,继续跟踪该地址向上看,还是之前的搜索方式。

不仅搜索到了0x84,前四个字节都搜索到了(而且在这里可以知道这26字节的结果所处的地址为0x1261ade0+26)

一个一个看

0x84

去看ida中的汇编代码,会发现这里是移动0x84这个固定值进去的,那这个就不用再管了,继续看

0x04

同样的,也是一个固定值

0xe0

这个在ida中看不出来什么,再加上有混淆,不如继续去看trace日志。

下面是踹死到的相关日志,跟踪方式与上面类似,这里不再重复。

0x12099ba8: "ldrb w9, [x11, w9, sxtw]" x11=0xe4ffdb50 w9=0x7 => w9=0xe0
0x1209a580: "ldrb w0, [x0, #7]" x0=0xe4ffdb50 => w0=0xe0
0x1209a588: "strb w0, [x21, #2]" w0=0xe0 x21=0x1261ade0 => w0=0xe0

再向上找就再也找不到了,下面的0xad也是类似,但是看上面的trace日志可以发现它俩来自于某个地址的后两个字节,经过多次踹死后确定如此,我就直接将其固定写死了,这两个字节后面会作为key的一部分被使用到,注意要保持前后一致。

这是前四个字节的来源,继续看后面的。后面的0000经过多次验证发现也是固定的,就不看了,现在就只剩下后20个字节了。

先看后面的0x90,还是之前的搜索方式

str(.*?)0x1261ade

简略分析后可以得出0x90是通过下面这些日志产生的

0x1209a5e4"ldrb w0, [x24, x20]" x24=0x1261ade6 x20=0x0 => w0=0xde
0x1209a5e8"and w21, w1, w0, lsl #1" w1=0xffffffaa w0=0xde => w21=0x1a8
0x1209a5ec"and w0, w11, w0, lsr #1" w11=0x55 w0=0xde => w0=0x45
0x1209a5f0"orr w0, w21, w0" w21=0x1a8 w0=0x45 => w0=0x1ed
0x1209a5f4"lsl w21, w0, #2" w21=0x1a8 w0=0x1ed => w21=0x7b4
0x1209a5f8"and w0, w12, w0, lsr #2" w12=0x33 w0=0x1ed => w0=0x33
0x1209a5fc"and w21, w21, #0xffffffcf" w21=0x7b4 => w21=0x784
0x1209a600"orr w0, w21, w0" w21=0x784 w0=0x33 => w0=0x7b7
0x1209a604"ubfx w21, w0, #4, #4" w21=0x784 w0=0x7b7 => w21=0xb
0x1209a608"bfi w21, w0, #4, #0x1c" w21=0xb w0=0x7b7 => w21=0x7b7b
0x1209a60c"eor w0, w21, w10" w21=0x7b7b w10=0xffffffeb => w0=0xffff8490   //0x...eb是固定的
0x1209a610"strb w0, [x24, x20]" w0=0xffff8490 x24=0x1261ade6 x20=0x0 => w0=0xffff8490

do {
// 位运算扰动处理
  v72 = (2 * (unsigned __int8)v54[v67]) & 0xFFAA | ((unsigned __int8)v54[v67] >> 1) & 0x55;
  v73 = (4 * v72) & 0xFFFFFFCF | (v72 >> 2) & 0x33;
  v54[v67] = (((unsigned __int8)v73 >> 4) | (16 * v73)) ^ ~(_BYTE)v53;
// 设置两个常量
  *(_DWORD *)(v19 - 124) = 144;
  *(_DWORD *)(v19 - 128) = 430;
// 对变量1做平方
  v74 = *(_DWORD *)(v19 - 124) * *(_DWORD *)(v19 - 124);
while (2 * (v74 & 1) + (v74 ^ 1) == 7 * *(_DWORD *)(v19 - 128) * *(_DWORD *)(v19 - 128));
//v54:这是实际参与变换的 buffer,可能是输入明文、密钥或中间加密态;
//v53:用于扰动当前位,是密钥轮次或调度值,分析来源很关键;
//整个位运算链 v72 → v73 → ^~v53:这是实现字节级加密或扰乱的核心流程;

这是其对应ida反编译后加上ai补充的注释,这段代码是在v54进行一些操作其中会使用到的变量为v67、v53,所以现在就很明确了,v54、v67、v53是需要逆向分析的目标,先去看看日志中分别对应的都是什么吧,将鼠标光标放到v54[v67]上后点击tab键。

发现其对应这一条日志,接着去踹死日志中搜索09a5e4这个地址。

发现v67只是一个计数器、循环变量(0,1,2....),0x1261ade6~0x1261ade6+20是我们要分析的v54的地址。

按照上述方式再看一眼v53

会发现之前固定的0xfff...eb就是v53,那就很清晰了,要分析的只有v54了

按照上述方式继续搜索0xde,下面是所有的相关来源

0x1209a424: "ldrb w21, [x24, w7, sxtw]" x24=0x1261ade6 w7=0x1 => w21=0x4c
0x1209a428: "ldrb w22, [x24, x20]" x24=0x1261ade6 x20=0x0 => w22=0x92
0x1209a42c: "eor w21, w22, w21" w22=0x92 w21=0x4c => w21=0xde
0x1209a430: "strb w21, [x24, x20]" w21=0xde x24=0x1261ade6 x20=0x0 => w21=0xde

到ida中去查看该地址,其对应的就是这句伪c代码,再结合上面踹死到的日志不难发现这是在做。

result[i]=v54[i]^v54[i+1] ,所以要继续向上找这个v54

0x1209a298: "lsr w21, w7, #4" w21=0x25900 w7=0x29 => w21=0x2
0x1209a29c: "bfi w21, w7, #4, #8" w21=0x2 w7=0x29 => w21=0x292
0x1209a2a0: "strb w21, [x24, x20]" w21=0x292 x24=0x1261ade6 x20=0x0 => w21=0x292

先跟到的是这里,去ida里看一眼伪c代码就知道是在做什么了

v54[(int)result= (v54[(int)result>>4&0xF | (16 * v54[(int)result]);

相当于是v54[i]单字节中的高四位和第四位置换位置,说白了就是2和9交换位置,所以在每次进行result[i]=v54[i]^v54[i+1] 操作前,会先对v54[i]进行一个小的置换,继续向上去跟v54的来源,最终是在这里生成的。

0x1209a054: "eor w10, w10, w13" w10=0xb1 w13=0xfd => w10=0x4c
0x1209a054: "eor w10, w10, w13" w10=0xb1 w13=0x98 => w10=0x29

do {
// 计算 v58 = v56 + 1,但如果 v56 是负数,则变成 v56 + 256
    v58 = v56 + 256;
if ((int)(v56 + 1) >= 0)
        v58 = v56 + 1;
// 将 v58 限制在 0-255 范围内(& 0xFFFFFF00 再取差值)
    v59 = v56 + 1 - (v58 & 0xFFFFFF00);  // v59 ∈ [0,255]
// 类似逻辑函数混淆:v60 ≈ v55 + v78[v59] + (v55 & v78[v59])
// 类似于 (v55 + v78[v59]) + (v55 & v78[v59]),一种非线性混合逻辑
    v60 = (v55 ^ (unsigned __int8)v78[v59]) + 2 * (v55 & v78[v59]);
// 为了制造分支干扰,判断 v60 是否为负数,决定是否采用原 v60 还是 v60 + 255 再归一
    v61 = v60 + 255;
if (v60 >= 0)
        v61 = (v55 ^ (unsigned __int8)v78[v59]) + 2 * (v55 & v78[v59]);
// 将 v60 限制到 0-255 范围
    v62 = v60 - (v61 & 0xFFFFFF00);
// 替换字节表:v78[v59] 和 v78[v62] 变成同一个值(固定写入 v63)
    v63 = v78[v62];
    v78[v59] = v63;
    v78[v62] = v63;
// 加密过程:用 `v78[...]` 中的一个混合索引来对 `v54[v57]` 做异或扰动
// 这个索引本质上是 `v78[v59] + v63` 再加上两者的按位与,得到的是某种非线性索引
    v54[v57] ^= v78[(unsigned __int8)((v78[v59] | v63) + (v78[v59] & v63))];
// 混淆分支,伪死循环控制变量
    *(_DWORD *)(v19 - 220) = 283;
    *(_DWORD *)(v19 - 224) = 139;

while (*(_DWORD *)(v19 - 220) * *(_DWORD *)(v19 - 220) + 1 == 7 * *(_DWORD *)(v19 - 224) * *(_DWORD *)(v19 - 224));
//v78 状态表 / 伪 S-box 类似 RC4 中的 S-box,用于映射和交换字节
//v54 加密目标 buffer 被加密的数据,最终结果写回其中

上面是ida中伪c代码结合ai注释后的代码块,ai已经帮我们分析好了,可以知道要继续跟踪的只有v78、v54了。

一个一个看

先看v78吧,这个"Sbox"的来源

其对应的地址为0xe4ffda40...,我们之前都是在日志中去进行的跟踪,这次用一下unidbg的tracewrite

可以看到,基本都是在是在0x99be8这个地方写入的,跳转到ida中去看一下。

do
{
// 1. v44 是用于判断触发写入逻辑的中间变量,混淆写法
    v44 = v43 + 311;
if (v43 + 56 >= 0)
        v44 = v43 + 56;
// 如果 (v43 + 56) 的低字节为 3,则执行特定字节写入
if (v43 + 56 - (v44 & 0xFFFFFF00) == 3)
        *(_BYTE *)(*(_QWORD *)(a3 + 16) + 3LL) = BYTE3(v87[0]); // 可能写入一个状态标记字节(第4字节)
// 2. v45 计算用于访问 v87 的偏移
    v45 = v43 + 7;
if (v43 >= 0)
        v45 = v43;
// 提取 v87 中低 8 字节的某一位(具体偏移经过混淆计算)
    v46 = *((unsigned __int8 *)v87 + (int)(v43 - (v45 & 0xFFFFFFF8)));
// 3. 构造中间扰动值 v47,通过复杂表达式扰动状态
    v47 = 2 * ((2 * (v42 | (unsigned __int8)v78[v43]) - (v42 ^ (unsigned __int8)v78[v43])) | v46)
        - ((2 * (v42 | (unsigned __int8)v78[v43]) - (v42 ^ (unsigned __int8)v78[v43])) ^ v46);
// 将 v47 限制在 0~255,等效于 v47 % 256(但混淆写法)
    v48 = v47 + 255;
if (v47 >= 0)
        v48 = v47;
    v49 = v47 - (v48 & 0xFFFFFF00);
// 使用 v49 的索引从状态表 v78 中获取扰动字节
    v50 = v78[v49];
    v78[v43] = v50; // 将该扰动写入当前索引位置,可能为伪加密表变换
// 4. 再次构造混淆表达式,作为一个判断条件入口
    v51 = ((2 * v43) & 0x44) + (v43 ^ 0x22);
    v52 = v51 + 255;
if (v51 >= 0)
        v52 = ((2 * v43) & 0x44) + (v43 ^ 0x22);
// 如果混淆后的 v51 的低字节值为 2,则调用某个子函数
if (v51 - (v52 & 0xFFFFFF00) == 2)
        ((void (__fastcall *)(__int64, _QWORD *, __int64, __int64, unsigned __int64, __int64, unsigned __int64, __int64))sub_16D4DC)(
            *(_QWORD *)(a3 + 16) + 4LL,  // 目标地址偏移为 4
            v87,                         // 输入数据块或扰动种子
2,                           // 固定参数
            v18, v15, v16, v7, v8);      // 多个上下文参数
// 恢复 v78[v49] 值(可能用于防止污染下一轮)
    v78[v49] = v50;
// 5. 更新索引 v43(混淆版 v43++)
    v43 = ((2 * v43) | 2) - (v43 ^ 1);
// 保存 v49 为下一轮使用的扰动状态
    v42 = v49;
}
while (v43 < 256); // 256轮,每轮处理一个索引字节
//是一个典型的 256轮 伪加密循环(和 RC4、Salsa20 初始化类似)
//v78 的 初始化过程:它是状态表核心,一般会涉及 key 或硬编码。
//v87 是 扰动源,来源很可能与设备信息、序列号、或者随机初始化有关。

这是ida中反编译出的伪c代码,和rc4类似,其中v78为Sbox、v87为key,分析一下之后发现v78会被初始化为0~255,正常的rc4初始化表,v87key其中除了有两个字节会变之外,其他都是固定的,这两个变化的字节跟gorgon加密结果中的第三和第四个字节是相同的,之前也提到过这个。

现在先稍微总结一下,v54为加密数据,根据v87key对v78Sbox进行初始化,之后再通过v78 Sbox对v54进行加密,最后在v54内部做一些运算,这相当于就是一个变种的rc4了(里面具体的运算步骤有些改变)。

所以现在只剩下加密入参v54的来源需要分析了,继续看v54吧,加密数据的来源

v54一共20字节,分别为98fd959500000000000000002000020568749f72

这里我们还是去tracewrite看,tracewite和在日志内追踪效果是一致的

打脸了,什么都没trace到,那说明什么了,说明他可能是是memcpy地址拷贝过来的,在日志中搜索一下,再次打脸。又是什么相关信息都没有,尝试在日志中搜索一下9595fd98

终于找到了

跳转到ida中后会发现

int *__fastcall sub_180F44(_DWORD *a1, int *a2, unsigned __int64 a3){
int v3; // w8
int v4; // w10
int v5; // w11
int v6; // w16
int v7; // w29
unsigned __int64 v8; // t2
int v9; // w17
int v10; // w16
int v11; // w14
int v12; // w13
int v13; // w3
int v14; // w4
int v15; // w14
int v16; // w30
int v17; // w21
int v18; // w22
int v19; // w7
int v20; // w23
int v21; // w6
int v22; // w16
int v23; // w25
int v24; // w20
int v25; // w5
int v26; // w27
int v27; // w24
int v28; // w23
int v29; // w22
int v30; // w9
int v31; // w14
int v32; // w9
int v33; // w19
int v34; // w24
int v35; // w25
int v36; // w3
int v37; // w25
int v38; // w21
int v39; // w26
int v40; // w6
int v41; // w9
int v42; // w22
int v43; // w22
int v44; // w23
int v45; // w24
int v46; // w22
int v47; // w25
int v48; // w27
int v49; // w26
int v50; // w27
int v51; // w9
int v52; // w27
int v53; // w27
int v54; // w24
int v55; // w25
int v56; // w24
int v57; // w26
int v58; // w24
int v59; // w24
int v60; // w9
int v61; // w28
int v62; // w15
int v63; // w27
int v64; // w25
int v65; // w26
int v66; // w27
int v67; // w9
int v68; // w27
int v69; // w15
int v70; // w27
int v71; // w25
int v72; // w27
int v73; // w26
int v74; // w27
int v75; // w9
int v76; // w27
int v77; // w15
int v78; // w28
int v79; // w26
int v80; // w25
int v81; // w27
int v82; // w9
int v83; // w15
int v84; // w25
int v85; // w26
unsignedint v86; // w9
int v87; // w9
int v88; // w25
int v89; // w27
int v90; // w15
int v91; // w27
int v92; // w26
int v93; // w28
int v94; // w9
int v95; // w15
int v96; // w15
int v97; // w27
int v98; // w25
int v99; // w25
int v100; // w24
int v101; // w9
int v102; // w24
int v103; // w15
int v104; // w24
int v105; // w24
int v106; // w24
int v107; // w26
int v108; // w25
int v109; // w27
int v110; // w15
int v111; // w9
int v112; // w15
int v113; // w26
int v114; // w20
int v115; // w24
int v116; // w23
int v117; // w24
int v118; // w9
int v119; // w7
int v120; // w15
int v121; // w4
int v122; // w7
int v123; // w7
int v124; // w9
int v125; // w17
int v126; // w15
int v127; // w17
int v128; // w17
int v129; // w4
int v130; // w16
int v131; // w5
int v132; // w15
int v133; // w9
int v134; // w15
int v135; // w3
int v136; // w13
int v138; // [xsp+Ch] [xbp-64h]
  v3 = a1[2];
  v4 = a1[3];
  v5 = a1[4];
  v6 = a1[5];
do
  {
    v7 = *a2;
    v138 = v6;
    a3 = ((2 * a3) & 0xFFFFFFFFFFFFFF7FLL) - (a3 ^ 0x40);
    a1[22] = *a2;
HIDWORD(v8) = ((v7 + (v5 & v4 | v6 & ~v4)) ^ 0xD76AA478) + v3 + ((2 * (v7 + (v5 & v4 | v6 & ~v4))) & 0xAED548F0);
LODWORD(v8) = HIDWORD(v8);
    v9 = a2[1];
    v10 = (v8 >> 25) + v4;
    v11 = (v10 & (v4 ^ v5) | v5) - (v10 & (v4 ^ v5) & v5);
    a1[23] = v9;
    v12 = a2[2];
HIDWORD(v8) = v138 + (v11 ^ v9) + 2 * (v11 & v9) - 389564586;
LODWORD(v8) = HIDWORD(v8);
    v13 = (v8 >> 20) + v10;
    a1[24] = v12;
    v14 = a2[3];
    v15 = (v10 & v13 | v4 & ~v13) + v12;
    a1[25] = v14;
    v16 = a2[4];
HIDWORD(v8) = ((((2 * v15) & 0x4840E1B6) + (v15 ^ 0x242070DB)) ^ v5)
                + 2 * ((((2 * v15) & 0x4840E1B6) + (v15 ^ 0x242070DB)) & v5);
LODWORD(v8) = HIDWORD(v8);
    v17 = (v8 >> 15) + v13;
HIDWORD(v8) = ((2 * ((v17 & v13 | v10 & ~v17) + v14)) | 0x837B9DDC)
                - (((v17 & v13 | v10 & ~v17) + v14) ^ 0xC1BDCEEE)
                + v4;
LODWORD(v8) = HIDWORD(v8);
    v18 = ((v8 >> 10) ^ v17) + 2 * ((v8 >> 10) & v17);
    a1[26] = v16;
    v19 = a2[5];
HIDWORD(v8) = v10 + v16 + (v18 & ((v17 | v13) - (v17 & v13)) ^ v13) - 176418897;
LODWORD(v8) = HIDWORD(v8);
    v20 = (v8 >> 25) + v18;
    v21 = 2 * (v18 & v20 | v17 & ~v20 | v19) - ((v18 & v20 | v17 & ~v20) ^ v19);
    a1[27] = v19;
    v22 = a2[6];
HIDWORD(v8) = 2 * ((((2 * v21) | 0x8F0F8C54) - (v21 ^ 0x4787C62A)) | v13)
                - ((((2 * v21) | 0x8F0F8C54) - (v21 ^ 0x4787C62A)) ^ v13);
LODWORD(v8) = HIDWORD(v8);
    v23 = ((v8 >> 20) ^ v20) + 2 * ((v8 >> 20) & v20);
    a1[28] = v22;
    v24 = a2[7];
    a1[29] = v24;
    v25 = a2[8];
HIDWORD(v8) = v17 + ((v23 & v20 | v18 & ~v23) ^ v22) + 2 * ((v23 & v20 | v18 & ~v23) & v22) - 1473231341;
LODWORD(v8) = HIDWORD(v8);
    v26 = ((v8 >> 15) ^ v23) + 2 * ((v8 >> 15) & v23);
    v27 = v25 + v20;
    v28 = (v26 & ((v23 | v20) - (v23 & v20)) ^ v20) + v24;
HIDWORD(v8) = ((((2 * v28) & 0xFA8D2A02) + (v28 ^ 0xFD469501)) ^ v18)
                + 2 * ((((2 * v28) & 0xFA8D2A02) + (v28 ^ 0xFD469501)) & v18);
LODWORD(v8) = HIDWORD(v8);
    v29 = 2 * ((v8 >> 10) | v26) - ((v8 >> 10) ^ v26);
    v30 = v29 & ~((v26 & v23) + ~(v26 | v23));
HIDWORD(v8) = v27 - (v30 & v23) + (v30 | v23) + 1770035416;
LODWORD(v8) = HIDWORD(v8);
    a1[30] = v25;
    v31 = a2[9];
    v32 = 2 * ((v8 >> 25) | v29) - ((v8 >> 25) ^ v29);
HIDWORD(v8) = v23 - ((v29 & v32 | v26 & ~v32) ^ v31) + 2 * (v29 & v32 | v26 & ~v32 | v31) - 1958414417;
LODWORD(v8) = HIDWORD(v8);
    a1[31] = v31;
    v33 = a2[10];
    v34 = 2 * ((v8 >> 20) | v32) - ((v8 >> 20) ^ v32);
    v35 = 2 * (v32 & v34 | v29 & ~v34 | v33) - ((v32 & v34 | v29 & ~v34) ^ v33);
    a1[32] = v33;
    v36 = a2[11];
HIDWORD(v8) = ((2 * v35) | 0xFFFEB762) - (v35 ^ 0xFFFF5BB1) + v26;
LODWORD(v8) = HIDWORD(v8);
    v37 = (v8 >> 15) + v34;
HIDWORD(v8) = v29 - ((v34 & v37 | v32 & ~v37) ^ v36) + 2 * (v34 & v37 | v32 & ~v37 | v36) - 1990404162;
LODWORD(v8) = HIDWORD(v8);
    a1[33] = v36;
    v38 = a2[12];
    v39 = 2 * ((v8 >> 10) | v37) - ((v8 >> 10) ^ v37);
HIDWORD(v8) = v32 - ((v39 & v37 | v34 & ~v39) ^ v38) + 2 * (v39 & v37 | v34 & ~v39 | v38) + 1804603682;
LODWORD(v8) = HIDWORD(v8);
    a1[34] = v38;
    v40 = a2[13];
    v41 = ((v8 >> 25) ^ v39) + 2 * ((v8 >> 25) & v39);
    v42 = (v41 & ((v39 | v37) - (v39 & v37)) | v37) - (v41 & ((v39 | v37) - (v39 & v37)) & v37);
    a1[35] = v40;
    v43 = 2 * (v42 | v40) - (v42 ^ v40) - 40341101;
    v44 = a2[14];
HIDWORD(v8) = 2 * (v43 | v34) - (v43 ^ v34);
LODWORD(v8) = HIDWORD(v8);
    v45 = (v8 >> 20) + v41;
    a1[36] = v44;
HIDWORD(v8) = v44 + v37 - (v45 & (v41 ^ v39) & v39) + (v45 & (v41 ^ v39) | v39) - 1502002290;
LODWORD(v8) = HIDWORD(v8);
    v46 = a2[15];
    v47 = (v8 >> 15) + v45;
    v48 = (v47 & ((v45 | v41) - (v45 & v41)) | v41) - (v47 & ((v45 | v41) - (v45 & v41)) & v41);
HIDWORD(v8) = v39 - (v48 ^ v46) + 2 * (v48 | v46) + 1236535329;
LODWORD(v8) = HIDWORD(v8);
    v49 = (v8 >> 10) + v47;
    v50 = ((v49 ^ v47) & v45 | v47) - ((v49 ^ v47) & v45 & v47);
HIDWORD(v8) = v41 + (v50 ^ v9) + 2 * (v50 & v9) - 165796510;
LODWORD(v8) = HIDWORD(v8);
    v51 = (v8 >> 27) + v49;
    v52 = (v47 & ~((v51 & v49) + ~(v51 | v49)) ^ v49) + v22;
HIDWORD(v8) = ((2 * v52) | 0x80816680) - (v52 ^ 0xC040B340) + v45;
LODWORD(v8) = HIDWORD(v8);
    v53 = 2 * ((v8 >> 23) | v51) - ((v8 >> 23) ^ v51);
    v54 = (((v53 | v51) - (v53 & v51)) & v49 | v51) - (((v53 | v51) - (v53 & v51)) & v49 & v51);
HIDWORD(v8) = (((v54 ^ v36) + 2 * (v54 & v36)) ^ 0x265E5A51)
                + v47
                + ((2 * ((v54 ^ v36) + 2 * (v54 & v36))) & 0x4CBCB4A2);
LODWORD(v8) = HIDWORD(v8);
    v55 = (v8 >> 18) + v53;
    v56 = (v55 & v51 | v53 & ~v51) + v7;
HIDWORD(v8) = (v56 ^ 0xE9B6C7AA) + v49 + ((2 * v56) & 0xD36D8F54);
LODWORD(v8) = HIDWORD(v8);
    v57 = (v8 >> 12) + v55;
    v58 = ((v57 ^ v55) & v53 | v55) - ((v57 ^ v55) & v53 & v55);
    v59 = 2 * (v58 | v19) - (v58 ^ v19) - 701558691;
HIDWORD(v8) = (v59 ^ v51) + 2 * (v59 & v51);
LODWORD(v8) = HIDWORD(v8);
    v60 = (v8 >> 27) + v57;
    v61 = (v60 & v55 | v57 & ~v55) + v33;
HIDWORD(v8) = ((((2 * v61) | 0x48828A6) - (v61 ^ 0x2441453)) ^ v53)
                + 2 * ((((2 * v61) | 0x48828A6) - (v61 ^ 0x2441453)) & v53);
LODWORD(v8) = HIDWORD(v8);
    v62 = ((v8 >> 23) ^ v60) + 2 * ((v8 >> 23) & v60);
    v63 = ((v62 ^ v60) & v57 | v60) - ((v62 ^ v60) & v57 & v60);
HIDWORD(v8) = v55 + (v63 ^ v46) + 2 * (v63 & v46) - 660478335;
LODWORD(v8) = HIDWORD(v8);
    v64 = (v8 >> 18) + v62;
HIDWORD(v8) = v57 - ((v64 & v60 | v62 & ~v60) ^ v16) + 2 * (v64 & v60 | v62 & ~v60 | v16) - 405537848;
LODWORD(v8) = HIDWORD(v8);
    v65 = (v8 >> 12) + v64;
    v66 = (v65 & v62 | v64 & ~v62) + v31;
HIDWORD(v8) = ((((2 * v66) & 0x43C39BCC) + (v66 ^ 0x21E1CDE6)) ^ v60)
                + 2 * ((((2 * v66) & 0x43C39BCC) + (v66 ^ 0x21E1CDE6)) & v60);
LODWORD(v8) = HIDWORD(v8);
    v67 = 2 * ((v8 >> 27) | v65) - ((v8 >> 27) ^ v65);
    v68 = ((v67 & v64 | v65 & ~v64) ^ v44) + 2 * ((v67 & v64 | v65 & ~v64) & v44) - 1019803690;
HIDWORD(v8) = 2 * (v68 | v62) - (v68 ^ v62);
LODWORD(v8) = HIDWORD(v8);
    v69 = (v8 >> 23) + v67;
    v70 = (v69 & v65 | v67 & ~v65) + v14;
HIDWORD(v8) = ((2 * v70) | 0xE9AA1B0E) - (v70 ^ 0xF4D50D87) + v64;
LODWORD(v8) = HIDWORD(v8);
    v71 = ((v8 >> 18) ^ v69) + 2 * ((v8 >> 18) & v69);
    v72 = 2 * (v71 & v67 | v69 & ~v67 | v25) - ((v71 & v67 | v69 & ~v67) ^ v25) + 1163531501;
HIDWORD(v8) = (v72 ^ v65) + 2 * (v72 & v65);
LODWORD(v8) = HIDWORD(v8);
    v73 = (v8 >> 12) + v71;
    v74 = (v73 & v69 | v71 & ~v69) + v40;
HIDWORD(v8) = (v74 ^ 0xA9E3E905) + v67 + ((2 * v74) & 0x53C7D20A);
LODWORD(v8) = HIDWORD(v8);
    v75 = (v8 >> 27) + v73;
    v76 = ((v75 | v73) - (v75 & v73)) & v71 ^ v73;
HIDWORD(v8) = v69 + (v76 ^ v12) + 2 * (v76 & v12) - 51403784;
LODWORD(v8) = HIDWORD(v8);
    v77 = (v8 >> 23) + v75;
    v78 = v38 + v73;
    v79 = v24 + (v73 & ~((v77 & v75) + ~(v77 | v75)) ^ v75) + 1735328473;
HIDWORD(v8) = (v79 ^ v71) + 2 * (v79 & v71);
LODWORD(v8) = HIDWORD(v8);
    v80 = 2 * ((v8 >> 18) | v77) - ((v8 >> 18) ^ v77);
HIDWORD(v8) = v78 + ((v80 ^ v77) & v75 ^ v77) - 1926607734;
LODWORD(v8) = HIDWORD(v8);
    v81 = 2 * ((v8 >> 12) | v80) - ((v8 >> 12) ^ v80);
HIDWORD(v8) = v75 - (v80 ^ v77 ^ v81 ^ v19) + 2 * (v80 ^ v77 ^ v81 | v19) - 378558;
LODWORD(v8) = HIDWORD(v8);
    v82 = (v8 >> 28) + v81;
HIDWORD(v8) = v25 + v77 - ((v82 ^ v81) & v80) + (v82 ^ v81 | v80) - 2022574463;
LODWORD(v8) = HIDWORD(v8);
    v83 = (v8 >> 21) + v82;
HIDWORD(v8) = v36 + v80 + (v82 ^ v81 ^ v83) + 1839030562;
LODWORD(v8) = HIDWORD(v8);
    v84 = v9 + v82;
    v85 = (v8 >> 16) + v83;
    v86 = ((2 * ((v83 ^ v82 ^ v85) + v44)) & 0xFBCA7018) + (((v83 ^ v82 ^ v85) + v44) ^ 0xFDE5380C);
HIDWORD(v8) = 2 * (v86 | v81) - (v86 ^ v81);
LODWORD(v8) = HIDWORD(v8);
    v87 = ((v8 >> 9) ^ v85) + 2 * ((v8 >> 9) & v85);
HIDWORD(v8) = v84 - ((v87 ^ v85) & v83) + (v87 ^ v85 | v83) - 1530992060;
LODWORD(v8) = HIDWORD(v8);
    v88 = 2 * ((v8 >> 28) | v87) - ((v8 >> 28) ^ v87);
    v89 = (v87 ^ v85 ^ v88 ^ v16) + 2 * ((v87 ^ v85 ^ v88) & v16) + 1272893353;
HIDWORD(v8) = 2 * (v89 | v83) - (v89 ^ v83);
LODWORD(v8) = HIDWORD(v8);
    v90 = (v8 >> 21) + v88;
    v91 = (v88 ^ v87 ^ v90 ^ v24) + 2 * ((v88 ^ v87 ^ v90) & v24);
HIDWORD(v8) = 2 * ((((2 * v91) & 0xED7696C0) + (v91 ^ 0xF6BB4B60)) | v85)
                - ((((2 * v91) & 0xED7696C0) + (v91 ^ 0xF6BB4B60)) ^ v85);
LODWORD(v8) = HIDWORD(v8);
    v92 = (v8 >> 16) + v90;
HIDWORD(v8) = v87 + (v90 ^ v88 ^ v92 ^ v33) + 2 * ((v90 ^ v88 ^ v92) & v33) - 1094730640;
LODWORD(v8) = HIDWORD(v8);
    v93 = v7 + v90;
    v94 = (v8 >> 9) + v92;
    v95 = 2 * (v92 ^ v90 ^ v94 | v40) - (v92 ^ v90 ^ v94 ^ v40) + 681279174;
HIDWORD(v8) = 2 * (v95 | v88) - (v95 ^ v88);
LODWORD(v8) = HIDWORD(v8);
    v96 = 2 * ((v8 >> 28) | v94) - ((v8 >> 28) ^ v94);
HIDWORD(v8) = v93 - ((v96 ^ v94) & v92) + (v96 ^ v94 | v92) - 358537222;
LODWORD(v8) = HIDWORD(v8);
    v97 = ((v8 >> 21) ^ v96) + 2 * ((v8 >> 21) & v96);
    v98 = 2 * (v96 ^ v94 ^ v97 | v14) - (v96 ^ v94 ^ v97 ^ v14);
HIDWORD(v8) = 2 * ((((2 * v98) | 0xA9DE610A) - (v98 ^ 0xD4EF3085)) | v92)
                - ((((2 * v98) | 0xA9DE610A) - (v98 ^ 0xD4EF3085)) ^ v92);
LODWORD(v8) = HIDWORD(v8);
    v99 = ((v8 >> 16) ^ v97) + 2 * ((v8 >> 16) & v97);
    v100 = v22 + 76029189 - ((v99 ^ v97) & v96) + (v99 ^ v97 | v96);
HIDWORD(v8) = (v100 ^ v94) + 2 * (v100 & v94);
LODWORD(v8) = HIDWORD(v8);
    v101 = (v8 >> 9) + v99;
    v102 = (((v101 | v99) - (v101 & v99)) ^ v97) + v31;
HIDWORD(v8) = ((((2 * v102) | 0xB3A9A072) - (v102 ^ 0xD9D4D039)) ^ v96)
                + 2 * ((((2 * v102) | 0xB3A9A072) - (v102 ^ 0xD9D4D039)) & v96);
LODWORD(v8) = HIDWORD(v8);
    v103 = (v8 >> 28) + v101;
    v104 = (v103 ^ v101 | v99) - ((v103 ^ v101) & v99);
    v105 = (v104 ^ v38) + 2 * (v104 & v38) - 421815835;
HIDWORD(v8) = 2 * (v105 | v97) - (v105 ^ v97);
LODWORD(v8) = HIDWORD(v8);
    v106 = (v8 >> 21) + v103;
    v107 = 2 * (((v106 | v103) - (v106 & v103)) ^ v101 | v46) - (((v106 | v103) - (v106 & v103)) ^ v101 ^ v46);
HIDWORD(v8) = ((2 * v107) | 0x3F44F9F0) - (v107 ^ 0x1FA27CF8) + v99;
LODWORD(v8) = HIDWORD(v8);
    v108 = (v8 >> 16) + v106;
    v109 = v7 + v103;
    v110 = v12 + (((v108 | v106) - (v108 & v106)) ^ v103) - 995338651;
HIDWORD(v8) = 2 * (v110 | v101) - (v110 ^ v101);
LODWORD(v8) = HIDWORD(v8);
    v111 = (v8 >> 9) + v108;
HIDWORD(v8) = v109 + ((v111 | ~v106) ^ v108) - 198630844;
LODWORD(v8) = HIDWORD(v8);
    v112 = (v8 >> 26) + v111;
    v113 = (v112 & ~v108 | v112 ^ ~v108) ^ v111;
HIDWORD(v8) = 2 * ((2 * (v113 | v24) - (v113 ^ v24) + 1126891415) | v106)
                - ((2 * (v113 | v24) - (v113 ^ v24) + 1126891415) ^ v106);
LODWORD(v8) = HIDWORD(v8);
    v114 = (v8 >> 22) + v112;
    v115 = (v114 | ~v111 | v112) - ((v114 | ~v111) & v112);
HIDWORD(v8) = ((2 * ((v115 ^ v44) + 2 * (v115 & v44))) | 0x5728474E)
                - (((v115 ^ v44) + 2 * (v115 & v44)) ^ 0xAB9423A7)
                + v108;
LODWORD(v8) = HIDWORD(v8);
    v116 = 2 * ((v8 >> 17) | v114) - ((v8 >> 17) ^ v114);
    v117 = (v116 | ~v112 | v114) - ((v116 | ~v112) & v114);
HIDWORD(v8) = ((2 * (2 * (v117 | v19) - (v117 ^ v19))) | 0xF9274072)
                - ((2 * (v117 | v19) - (v117 ^ v19)) ^ 0xFC93A039)
                + v111;
LODWORD(v8) = HIDWORD(v8);
    v118 = (v8 >> 11) + v116;
    v119 = (v118 | ~v114 | v116) - ((v118 | ~v114) & v116);
HIDWORD(v8) = (((v119 ^ v38) + 2 * (v119 & v38)) ^ 0x655B59C3)
                + v112
                + ((2 * ((v119 ^ v38) + 2 * (v119 & v38))) & 0xCAB6B386);
LODWORD(v8) = HIDWORD(v8);
    v120 = (v8 >> 26) + v118;
HIDWORD(v8) = 2 * ((2 * ((v120 | ~v116) ^ v118 | v14) - ((v120 | ~v116) ^ v118 ^ v14) - 1894986606) | v114)
                - ((2 * ((v120 | ~v116) ^ v118 | v14) - ((v120 | ~v116) ^ v118 ^ v14) - 1894986606) ^ v114);
LODWORD(v8) = HIDWORD(v8);
    v121 = (v8 >> 22) + v120;
    v122 = ((v121 | ~v118) ^ v120 ^ v33) + 2 * (((v121 | ~v118) ^ v120) & v33) - 1051523;
HIDWORD(v8) = (v122 ^ v116) + 2 * (v122 & v116);
LODWORD(v8) = HIDWORD(v8);
    v123 = ((v8 >> 17) ^ v121) + 2 * ((v8 >> 17) & v121);
HIDWORD(v8) = v118 + ((v123 | ~v120) ^ v121 ^ v9) + 2 * (((v123 | ~v120) ^ v121) & v9) - 2054922799;
LODWORD(v8) = HIDWORD(v8);
    v124 = ((v8 >> 11) ^ v123) + 2 * ((v8 >> 11) & v123);
    v125 = (((v124 & v121) + ~v121) | v123) - (((v124 & v121) + ~v121) & v123);
HIDWORD(v8) = 2 * (((v125 ^ v25) + 2 * (v125 & v25) + 1873313359) | v120)
                - (((v125 ^ v25) + 2 * (v125 & v25) + 1873313359) ^ v120);
LODWORD(v8) = HIDWORD(v8);
    v126 = 2 * ((v8 >> 26) | v124) - ((v8 >> 26) ^ v124);
    v127 = (v126 | ~v123 | v124) - ((v126 | ~v123) & v124) + v46;
HIDWORD(v8) = ((((2 * v127) | 0xFC59CDC0) - (v127 ^ 0xFE2CE6E0)) ^ v121)
                + 2 * ((((2 * v127) | 0xFC59CDC0) - (v127 ^ 0xFE2CE6E0)) & v121);
LODWORD(v8) = HIDWORD(v8);
    v128 = 2 * ((v8 >> 22) | v126) - ((v8 >> 22) ^ v126);
    v129 = (v128 | ~v124 | v126) - ((v128 | ~v124) & v126);
HIDWORD(v8) = ((2 * (v129 | v22) - (v129 ^ v22)) ^ 0xA3014314)
                + v123
                + ((2 * (2 * (v129 | v22) - (v129 ^ v22))) & 0x46028628);
LODWORD(v8) = HIDWORD(v8);
    v130 = (v8 >> 17) + v128;
    v131 = v16 + v126;
    v132 = v40 + (((v130 & v126) + ~v126) ^ v128) + 1309151649;
HIDWORD(v8) = 2 * (v132 | v124) - (v132 ^ v124);
LODWORD(v8) = HIDWORD(v8);
    v133 = ((v8 >> 11) ^ v130) + 2 * ((v8 >> 11) & v130);
HIDWORD(v8) = v131 + (((v133 & v128) + ~v128) ^ v130) - 145523070;
LODWORD(v8) = HIDWORD(v8);
    v134 = 2 * ((v8 >> 26) | v133) - ((v8 >> 26) ^ v133);
HIDWORD(v8) = v36 + v128 + ((v134 | ~v130) ^ v133) - 1120210379;
LODWORD(v8) = HIDWORD(v8);
    v135 = 2 * ((v8 >> 22) | v134) - ((v8 >> 22) ^ v134);
HIDWORD(v8) = v130 - (((v135 & v133) + ~v133) ^ v134 ^ v12) + 2 * (((v135 & v133) + ~v133) ^ v134 | v12) + 718787259;
LODWORD(v8) = HIDWORD(v8);
    v136 = 2 * ((v8 >> 17) | v135) - ((v8 >> 17) ^ v135);
    v3 += v134;
HIDWORD(v8) = ((((v136 | ~v134) ^ v135) + v31) ^ 0xEB86D391)
                + v133
                + ((2 * (((v136 | ~v134) ^ v135) + v31)) & 0xD70DA722);
LODWORD(v8) = HIDWORD(v8);
    v6 = v135 + v138;
    v5 += v136;
    v4 += ((v8 >> 11) ^ v136) + 2 * ((v8 >> 11) & v136);
    a2 += 16;
    a1[37] = v46;
  }
while ( a3 );
  a1[2] = v3;
  a1[3] = v4;
  a1[4] = v5;
  a1[5] = v6;
return a2;
}

好家伙,这不是md5吗,先看看是不是标准的md5吧,在unidbg中对sub_180F44下断点,找入参去验证一下是不是标准md5。

怀疑是对这段截取的uri进行的md5,到在线网站上去做一下验证。

okay,结果的前四字节跟之前去找的一模一样,那就是这个了

后面8个字节全是0,其实跟我第一次搞得还不太一样,我第一次搞得时候不记得什么接口了后面的前四个字节来源于header中的x-ss-stub的前四个字节,现在这个入参不是之前的了,用的是是用户主页视频列表的接口的入参,header里面并不存在x-ss-xtub,可能是这个原因导致的变化。98fd959500000000000000002000020568749f72

再后面的20000205适合版本有关,这个就不管了,可以直接固定住

再看一下最后的68749f72

直接在踹死的日志中搜

继续搜索68749f72

最前面的是在这里,再向上就没有相关逻辑了,怀疑是0x02d49c这里生成的,在ida中查看。

发现这里其实是gettimeofday获取当前时间的,现在的时间戳不都应该175开头吗,为什么这里是0x68开头的呢,因为这是16进制,拿到计算其中转换一下就明白了。

好了,确实没有错,那v54就确定了。

v54确定了,这篇文章的主体内容也就到此结束了。剩下的就只是去复现加密过程中的运算逻辑了。

*本文为看雪论坛优秀文章,由 git_21210wzzzh2025原创,转载请注明来自看雪社区

SDC 2025 早鸟票限时开售!议题火热征集中~

# 往期推荐

安卓旧系统 OTA 包分析与漏洞提权适配

XCTF L3HCTF 2025 pwn 方向解题思路

Pwn题解析|L3CTF 2025 heack & heack_revenge

OLLVM-BR间接混淆去除

House of Einherjar

球分享

球点赞

球在看

点击阅读原文查看更多

阅读原文

跳转微信打开

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

X-Gorgon Android加解密 逆向工程 unidbg RC4 算法分析 移动安全 X-Gorgon encryption Android encryption/decryption Reverse engineering RC4 algorithm Algorithm analysis Mobile security
相关文章