湖北校园网PC端拨号算法逆向

前言

上一文 PPPoE中间人拦截以及校园网突破漫谈我们谈到使用 PPPoE 拦截来获取真实的账号密码。
在这个的基础上,我对我们湖北的客户端进行了逆向,得到了拨号加密算法。

准备工作

首先查壳,发现这个版本没壳了,我记得之前好像是加过 vmp 的呀,不管了。
然后我们看看目录下的 dll 导出表看看有没有什么好东西

AidcComm.dll 里面有这些东西,看来这个极大可能会是我们的目标。

我们再看看主程序的导入表,发现主程序的导入表里面并没有这个 dll,那我们动态调试的时候应该怎么断到这个 dll 中去呢。
没有导入表说明没有 .lib,那有可能是通过 LoadLibrary 加载的 dll,至于自实现 peloader,我觉得应该这个软件应该不会是这样。
看看就知道了。
直接用 x32dbg 和 IDA 开始看。

逆向过程

x32dbg 打开主程序,然后 bp LoadLibraryW,再重新载入程序,我们可以一步步运行发现 AidcComm.dll 被载入了。
然后运行到用户代码处

我们可以看到此时 eax 寄存器的值为 55870000,这个就是 LoadLibrary 返回的 HANDLE。一般思路来说,接下来就是用 GetProcAddress 获取导出表函数的地址了。
继续往下走几步,即可发现我们的猜测并没有错误。

从这张图我们可以看到主程序获取了 AidcComm.GetPWD 和 AidcComm.GetRegularAccount 的地址。
那我们通过 call 之后的 eax 跳转过去在这两个函数的地址下断,直接跑起来。
然后我们会发现在 AidcComm.GetRegularAccount 断下来了,传入的参数可以在堆栈窗口中看到。

我们去 IDA 分析 GetRegularAccount 这个函数,同时在调试器这边动态跟(这个我已经分析过了,所以有的变量和函数名我已经改过了)

首先最直观的就是账号的变换,账号只需要加上前缀 !^Wnds0 即可(但其实加密出来后,主程序这个给它又加了一个后缀 @hbxy)。(从调试器可以看到)
密码我们直接跟到 GetPWD 里面去看。

通过调试器我们可以观察出,这个分支结构只会执行 a2 == 1 这个分支。
看来是通过下面这个函数加密的了。(我给他改了名 encryptPwdWithKey)
我们进到 encryptPwdWithKey(void *password, char *key, rsize_t SizeInBytes) 这个函数去查看。

通过分析我们可以得出大致上的流程

  1. password 用 key RC4 一下得到 A
  2. 把 A md5 一下得到 B,如果第 11 位为奇数,取 B 的前 16 位,偶数就后 16 位,得到 C
  3. C 再用 key RC4 一下得到 D
  4. D 再 md5 一下,取 [8:24]得到 E

也就是最后得到的 E 是加密之后的。

可能有的小伙伴不明白为什么会是 RC4,这里有几个提示的地方,第一是这个字符串的提示,第二是 RC4 加密流程是很容易分辨的,这个靠经验了。

但是我们发现我们截取出来的密码和这个是有点小不一样的。通过调试,可以看到在 GetRegularAccount 函数加密出来后,又调用了一个函数,这个函数我给它重命名为 fixHBKey 了。

我们跟进去看看

代码并不长,我们可以直接调试器分析,如果你想用 IDA 也是可以的,IDA 可以搜索上图中的 <<< FixHBKey: %s <<< 这个字符串来定位这个函数。
或者我们可以看到这个函数的入口地址为 001115D0,这个 exe 的加载基址我们可以往上滑到顶看到为 000F1000,两个之间的差值为 205D0
然后再把这个差值加上 IDA 加载的基址,即可找到这个函数。

这个函数的大致作用就是修改上面我们得到的 E

  • E[今天几号日期 % 16] 替换为 'b' 得到最后的密码

这块我们是搞清楚了,那 key 是怎么来的呢。
这个我们就需要大量借助调试器了,我们重启一下主程序,然后在上面的分析基础上找到这个 key 第一次出现的地方,我们可以发现
在 AidcRes 偏移 10110 处即为 key 的生成函数。

这个函数巨长,同样的,我们借助之前的方法在 IDA 中找到这个函数,我这里直接按偏移,可以看到在 sub_420110 即为我们的加密函数,
这里我已经重命名为 generateKey。

这个函数太长了,我无法截全图,我直接丢代码然后分析,这里分析建议大家调试结合代码来看,不然一头雾水。其中大量的必要变量和函数我已经重命名,方便大家阅读。

int __thiscall generateKey(char *this, int a2, char a3, int a4, int a5, int a6, int a7, int a8)
{int v8; // eaxint v9; // edxint v11; // [esp+8h] [ebp-37Ch]char *v12; // [esp+20h] [ebp-364h]int len_username_b_MonthDay; // [esp+24h] [ebp-360h]char *v14; // [esp+28h] [ebp-35Ch]int len_bUsernameMonthDay; // [esp+2Ch] [ebp-358h]char *v16; // [esp+30h] [ebp-354h]char *mem_17; // [esp+34h] [ebp-350h]int v18; // [esp+38h] [ebp-34Ch]int lenMonthDay; // [esp+3Ch] [ebp-348h]int lenUsername; // [esp+40h] [ebp-344h]int v21; // [esp+44h] [ebp-340h]int v22; // [esp+48h] [ebp-33Ch]int *v23; // [esp+4Ch] [ebp-338h]int v24; // [esp+50h] [ebp-334h]const char *v25; // [esp+54h] [ebp-330h]int len_HbKeyGa; // [esp+58h] [ebp-32Ch]int lenHbKeyGa; // [esp+5Ch] [ebp-328h]char *pMem_64_a; // [esp+60h] [ebp-324h]int len_HbKeyGb; // [esp+64h] [ebp-320h]int lenHbKeyGb; // [esp+68h] [ebp-31Ch]char *pMem_64_b; // [esp+6Ch] [ebp-318h]int v32; // [esp+70h] [ebp-314h]int v33; // [esp+74h] [ebp-310h]int v34; // [esp+78h] [ebp-30Ch]int v35; // [esp+7Ch] [ebp-308h]int len_monthDay_Username_b; // [esp+80h] [ebp-304h]char *v37; // [esp+84h] [ebp-300h]int len_username_MonthDay_b; // [esp+88h] [ebp-2FCh]LPVOID lp_mix_md5_1; // [esp+8Ch] [ebp-2F8h]size_t v40; // [esp+90h] [ebp-2F4h]int v41; // [esp+94h] [ebp-2F0h]LPVOID v42; // [esp+98h] [ebp-2ECh]LPVOID v43; // [esp+9Ch] [ebp-2E8h]LPVOID v44; // [esp+A0h] [ebp-2E4h]int index3; // [esp+A4h] [ebp-2E0h]int index2; // [esp+A8h] [ebp-2DCh]char *pHbKeyGa; // [esp+ACh] [ebp-2D8h]int index6; // [esp+B0h] [ebp-2D4h]int index5; // [esp+B4h] [ebp-2D0h]_DWORD *md5_monthDay_Username_b; // [esp+B8h] [ebp-2CCh]_DWORD *md5_username_b_MonthDay; // [esp+BCh] [ebp-2C8h]_DWORD *md5_username_MonthDay_b; // [esp+C0h] [ebp-2C4h]void *mix_md5_1; // [esp+C4h] [ebp-2C0h]int md5_1_pLus3remainder4; // [esp+C8h] [ebp-2BCh]int md5_bUsernameMonthDay; // [esp+CCh] [ebp-2B8h]char *pHbKeyGb; // [esp+D0h] [ebp-2B4h]void *v57; // [esp+D4h] [ebp-2B0h]void *v58; // [esp+D8h] [ebp-2ACh]int md5_4_plus5remainer4; // [esp+DCh] [ebp-2A8h]void *mix_md5_2; // [esp+E0h] [ebp-2A4h]const char *userName; // [esp+E4h] [ebp-2A0h]char *monthDay; // [esp+E8h] [ebp-29Ch]char *bUsernameMonthDay; // [esp+ECh] [ebp-298h]char *username_b_MonthDay; // [esp+F0h] [ebp-294h]char *username_MonthDay_b; // [esp+F4h] [ebp-290h]char *monthDay_Username_b; // [esp+F8h] [ebp-28Ch]char *p_HbKeyGb; // [esp+FCh] [ebp-288h]char *p_HbKeyGa; // [esp+100h] [ebp-284h]const char *username; // [esp+104h] [ebp-280h]_DWORD *md5_2; // [esp+108h] [ebp-27Ch]_DWORD *md5_3; // [esp+10Ch] [ebp-278h]int index1; // [esp+114h] [ebp-270h]int index4; // [esp+118h] [ebp-26Ch]int temp1; // [esp+11Ch] [ebp-268h]int temp2; // [esp+120h] [ebp-264h]_DWORD *md5_4; // [esp+124h] [ebp-260h]int md5_1; // [esp+128h] [ebp-25Ch]size_t SizeInBytes; // [esp+134h] [ebp-250h]char *DstBuf; // [esp+138h] [ebp-24Ch]char *pThis; // [esp+13Ch] [ebp-248h]int v81; // [esp+140h] [ebp-244h]int v82; // [esp+144h] [ebp-240h]int v83; // [esp+148h] [ebp-23Ch]int v84; // [esp+14Ch] [ebp-238h]int v85; // [esp+150h] [ebp-234h]int v86; // [esp+154h] [ebp-230h]int v87; // [esp+158h] [ebp-22Ch]int v88; // [esp+15Ch] [ebp-228h]char hbKey; // [esp+160h] [ebp-224h]char v90; // [esp+161h] [ebp-223h]char hbKeyGa; // [esp+1E4h] [ebp-1A0h]char mem_64_a; // [esp+1E5h] [ebp-19Fh]char hbKeyGb; // [esp+228h] [ebp-15Ch]char mem_64_b; // [esp+229h] [ebp-15Bh]char v95; // [esp+22Fh] [ebp-155h]char v96[4]; // [esp+26Ch] [ebp-118h]char v97[5]; // [esp+270h] [ebp-114h]int v98; // [esp+275h] [ebp-10Fh]int v99; // [esp+279h] [ebp-10Bh]int v100; // [esp+27Dh] [ebp-107h]int v101; // [esp+281h] [ebp-103h]int v102; // [esp+285h] [ebp-FFh]__int16 v103; // [esp+289h] [ebp-FBh]char v104; // [esp+28Bh] [ebp-F9h]char v105[4]; // [esp+28Ch] [ebp-F8h]char v106[5]; // [esp+290h] [ebp-F4h]int v107; // [esp+295h] [ebp-EFh]int v108; // [esp+299h] [ebp-EBh]int v109; // [esp+29Dh] [ebp-E7h]int v110; // [esp+2A1h] [ebp-E3h]int v111; // [esp+2A5h] [ebp-DFh]__int16 v112; // [esp+2A9h] [ebp-DBh]char v113; // [esp+2ABh] [ebp-D9h]char v114[4]; // [esp+2ACh] [ebp-D8h]char v115[5]; // [esp+2B0h] [ebp-D4h]int v116; // [esp+2B5h] [ebp-CFh]int v117; // [esp+2B9h] [ebp-CBh]int v118; // [esp+2BDh] [ebp-C7h]int v119; // [esp+2C1h] [ebp-C3h]int v120; // [esp+2C5h] [ebp-BFh]__int16 v121; // [esp+2C9h] [ebp-BBh]char v122; // [esp+2CBh] [ebp-B9h]char v123[4]; // [esp+2CCh] [ebp-B8h]char v124[5]; // [esp+2D0h] [ebp-B4h]int v125; // [esp+2D5h] [ebp-AFh]int v126; // [esp+2D9h] [ebp-ABh]int v127; // [esp+2DDh] [ebp-A7h]int v128; // [esp+2E1h] [ebp-A3h]int v129; // [esp+2E5h] [ebp-9Fh]__int16 v130; // [esp+2E9h] [ebp-9Bh]char v131; // [esp+2EBh] [ebp-99h]char char_array_29_2[29]; // [esp+2ECh] [ebp-98h]__int16 v133; // [esp+309h] [ebp-7Bh]char v134; // [esp+30Bh] [ebp-79h]char char_array_29_1[29]; // [esp+30Ch] [ebp-78h]__int16 v136; // [esp+329h] [ebp-5Bh]char v137; // [esp+32Bh] [ebp-59h]char char_array_29_3[29]; // [esp+32Ch] [ebp-58h]__int16 v139; // [esp+349h] [ebp-3Bh]char v140; // [esp+34Bh] [ebp-39h]char char_array_29_4[29]; // [esp+34Ch] [ebp-38h]__int16 v142; // [esp+369h] [ebp-1Bh]char v143; // [esp+36Bh] [ebp-19h]char month_day; // [esp+36Ch] [ebp-18h]int v145; // [esp+36Dh] [ebp-17h]int v146; // [esp+380h] [ebp-4h]pThis = this;v41 = 0;v146 = 0;username = 0;v40 = sub_421680("@hbxy", 0);if ( v40 != -1 ){v33 = sub_421630((int)&v11, 0, v40);std::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator=(v33);std::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string<char,std::char_traits<char>,std::allocator<char>>(&v11);}username = (const char *)get_username(&a3);userName = username;v25 = username + 1;userName += strlen(userName);v24 = ++userName - (username + 1);lenUsername = userName - (username + 1);month_day = 0;v145 = 0;strftime(&month_day, 5u, "%m%d", (const struct tm *)(pThis + 8));monthDay = &month_day;v23 = &v145;monthDay += strlen(monthDay);v21 = ++monthDay - (char *)&v145;lenMonthDay = monthDay - (char *)&v145;(*(void (**)(char *, const char *, ...))(*(_DWORD *)pThis + 4))(pThis, ">>> GetHBKey: %s >>>", &month_day);v18 = 1;SizeInBytes = lenMonthDay + lenUsername + 2;mem_17 = (char *)malloc(SizeInBytes);DstBuf = mem_17;memset(mem_17, 0, SizeInBytes);sprintf_s(DstBuf, SizeInBytes, "%c%s%s", pThis[4], username, &month_day);// "b177628979080516"bUsernameMonthDay = DstBuf;v16 = DstBuf + 1;bUsernameMonthDay += strlen(bUsernameMonthDay);len_bUsernameMonthDay = ++bUsernameMonthDay - (DstBuf + 1);md5_bUsernameMonthDay = md5_StrWithLength(DstBuf, bUsernameMonthDay - (DstBuf + 1));// 5e64fdaa6449e2abb9693f2757c11652(*(void (**)(char *, const char *, ...))(*(_DWORD *)pThis + 4))(pThis,"[HBKEY] mdata1: %s [%s]",DstBuf,md5_bUsernameMonthDay);memset(DstBuf, 0, SizeInBytes);sprintf_s(DstBuf, SizeInBytes, "%s%c%s", username, pThis[4], &month_day);// "17762897908b0516"username_b_MonthDay = DstBuf;v14 = DstBuf + 1;username_b_MonthDay += strlen(username_b_MonthDay);len_username_b_MonthDay = ++username_b_MonthDay - (DstBuf + 1);md5_username_b_MonthDay = (_DWORD *)md5_StrWithLength(DstBuf, username_b_MonthDay - (DstBuf + 1));// 16dffe496172e2fb1bdb9b2002bfb5a5(*(void (**)(char *, const char *, ...))(*(_DWORD *)pThis + 4))(pThis,"[HBKEY] mdata2: %s [%s]",DstBuf,md5_username_b_MonthDay);memset(DstBuf, 0, SizeInBytes);sprintf_s(DstBuf, SizeInBytes, "%s%s%c", username, &month_day, pThis[4]);// "177628979080516b"username_MonthDay_b = DstBuf;v12 = DstBuf + 1;username_MonthDay_b += strlen(username_MonthDay_b);len_username_MonthDay_b = ++username_MonthDay_b - (DstBuf + 1);md5_username_MonthDay_b = (_DWORD *)md5_StrWithLength(DstBuf, username_MonthDay_b - (DstBuf + 1));// 6614da7943beed0e7baafc0be7fb624c(*(void (**)(char *, const char *, ...))(*(_DWORD *)pThis + 4))(pThis,"[HBKEY] mdata3: %s [%s]",DstBuf,md5_username_MonthDay_b);memset(DstBuf, 0, SizeInBytes);sprintf_s(DstBuf, SizeInBytes, "%s%s%c", &month_day, username, pThis[4]);// "051617762897908b"monthDay_Username_b = DstBuf;v37 = DstBuf + 1;monthDay_Username_b += strlen(monthDay_Username_b);len_monthDay_Username_b = ++monthDay_Username_b - (DstBuf + 1);md5_monthDay_Username_b = (_DWORD *)md5_StrWithLength(DstBuf, monthDay_Username_b - (DstBuf + 1));// 2b28feebb48c0cb98b9f3da404fff646(*(void (**)(char *, const char *, ...))(*(_DWORD *)pThis + 4))(pThis,"[HBKEY] mdata4: %s [%s]",DstBuf,md5_monthDay_Username_b);md5_1 = 0;md5_2 = 0;md5_3 = 0;md5_4 = 0;if ( *(char *)(md5_bUsernameMonthDay + 1) % 2 ){md5_1 = md5_bUsernameMonthDay;md5_2 = md5_username_MonthDay_b;md5_3 = md5_username_b_MonthDay;md5_4 = md5_monthDay_Username_b;}else{md5_1 = md5_bUsernameMonthDay;md5_2 = md5_monthDay_Username_b;md5_3 = md5_username_b_MonthDay;md5_4 = md5_username_MonthDay_b;}hbKeyGa = 0;memset(&mem_64_a, 0, 0x40u);md5_1_pLus3remainder4 = *(char *)(md5_1 + 3) % 4;// 以下一连串的赋值是使 char_array_29_1 = md5_1, char_array_29_2 = md5_2char_array_29_1[0] = 0;*(_DWORD *)&char_array_29_1[1] = 0;*(_DWORD *)&char_array_29_1[5] = 0;*(_DWORD *)&char_array_29_1[9] = 0;*(_DWORD *)&char_array_29_1[13] = 0;*(_DWORD *)&char_array_29_1[17] = 0;*(_DWORD *)&char_array_29_1[21] = 0;*(_DWORD *)&char_array_29_1[25] = 0;v136 = 0;v137 = 0;char_array_29_2[0] = 0;*(_DWORD *)&char_array_29_2[1] = 0;*(_DWORD *)&char_array_29_2[5] = 0;*(_DWORD *)&char_array_29_2[9] = 0;*(_DWORD *)&char_array_29_2[13] = 0;*(_DWORD *)&char_array_29_2[17] = 0;*(_DWORD *)&char_array_29_2[21] = 0;*(_DWORD *)&char_array_29_2[25] = 0;v133 = 0;v134 = 0;*(_DWORD *)char_array_29_1 = *(_DWORD *)md5_1;*(_DWORD *)&char_array_29_1[4] = *(_DWORD *)(md5_1 + 4);*(_DWORD *)&char_array_29_1[8] = *(_DWORD *)(md5_1 + 8);*(_DWORD *)&char_array_29_1[12] = *(_DWORD *)(md5_1 + 12);*(_DWORD *)&char_array_29_1[16] = *(_DWORD *)(md5_1 + 16);*(_DWORD *)&char_array_29_1[20] = *(_DWORD *)(md5_1 + 20);*(_DWORD *)&char_array_29_1[24] = *(_DWORD *)(md5_1 + 24);*(_DWORD *)&char_array_29_1[28] = *(_DWORD *)(md5_1 + 28);*(_DWORD *)char_array_29_2 = *md5_2;*(_DWORD *)&char_array_29_2[4] = md5_2[1];*(_DWORD *)&char_array_29_2[8] = md5_2[2];*(_DWORD *)&char_array_29_2[12] = md5_2[3];*(_DWORD *)&char_array_29_2[16] = md5_2[4];*(_DWORD *)&char_array_29_2[20] = md5_2[5];*(_DWORD *)&char_array_29_2[24] = md5_2[6];*(_DWORD *)&char_array_29_2[28] = md5_2[7];v81 = md5_1_pLus3remainder4;                  // 0v82 = abs(md5_1_pLus3remainder4 - 5) % 4;     // 1v8 = (md5_1_pLus3remainder4 + 2) % 4;         // 2v83 = (md5_1_pLus3remainder4 + 2) % 4;        // 2v84 = abs(md5_1_pLus3remainder4 - 3);         // 3v96[0] = 0;*(_DWORD *)&v96[1] = 0;*(_DWORD *)&v97[1] = 0;v98 = 0;v99 = 0;v100 = 0;v101 = 0;v102 = 0;v103 = 0;v104 = 0;v105[0] = 0;*(_DWORD *)&v105[1] = 0;*(_DWORD *)&v106[1] = 0;v107 = 0;v108 = 0;v109 = 0;v110 = 0;v111 = 0;v112 = 0;v113 = 0;*(_DWORD *)v96 = *(_DWORD *)&char_array_29_1[8 * md5_1_pLus3remainder4];*(_DWORD *)v97 = *(_DWORD *)&char_array_29_1[8 * md5_1_pLus3remainder4 + 4];*(_DWORD *)&v97[4] = *(_DWORD *)&char_array_29_2[8 * v82];*(int *)((char *)&v98 + 3) = *(_DWORD *)&char_array_29_2[8 * v82 + 4];*(int *)((char *)&v99 + 3) = *(_DWORD *)&char_array_29_1[8 * v8];*(int *)((char *)&v100 + 3) = *(_DWORD *)&char_array_29_1[8 * v8 + 4];*(int *)((char *)&v101 + 3) = *(_DWORD *)&char_array_29_2[8 * v84];*(int *)((char *)&v102 + 3) = *(_DWORD *)&char_array_29_2[8 * v84 + 4];*(_DWORD *)v105 = *(_DWORD *)&char_array_29_2[8 * md5_1_pLus3remainder4];*(_DWORD *)v106 = *(_DWORD *)&char_array_29_2[8 * md5_1_pLus3remainder4 + 4];*(_DWORD *)&v106[4] = *(_DWORD *)&char_array_29_1[8 * v82];*(int *)((char *)&v107 + 3) = *(_DWORD *)&char_array_29_1[8 * v82 + 4];*(int *)((char *)&v108 + 3) = *(_DWORD *)&char_array_29_2[8 * v8];*(int *)((char *)&v109 + 3) = *(_DWORD *)&char_array_29_2[8 * v8 + 4];*(int *)((char *)&v110 + 3) = *(_DWORD *)&char_array_29_1[8 * v84];*(int *)((char *)&v111 + 3) = *(_DWORD *)&char_array_29_1[8 * v84 + 4];mix_md5_1 = (void *)md5_StrWithLength(v96, 32);// 第一个参数  5e64fdaa43beed0eb9693f27e7fb624c6614da796449e2ab7baafc0b57c11652  // 返回值  5008ef506febfc228802dd43b99c1869// 为 5e64fdaa43beed0eb9693f27e7fb624c 的 md5mix_md5_2 = (void *)md5_StrWithLength(v105, 32);// 第一个参数  6614da796449e2ab7baafc0b57c11652// 返回值  46e4a9da513469a20da82e3136f46951sprintf_s(&hbKeyGa, 0x41u, "%s%s", mix_md5_1, mix_md5_2);// hbKeyGa = "5008ef506febfc228802dd43b99c186946e4a9da513469a20da82e3136f46951"lp_mix_md5_1 = mix_md5_1;j_j___free_base(mix_md5_1);if ( lp_mix_md5_1 ){mix_md5_1 = (void *)33059;v35 = 33059;}else{v35 = 0;}v44 = mix_md5_2;j_j___free_base(mix_md5_2);if ( v44 ){mix_md5_2 = (void *)33059;v34 = 33059;}else{v34 = 0;}(*(void (**)(char *, const char *, ...))(*(_DWORD *)pThis + 4))(pThis, "[HBKEY] ga: %s", &hbKeyGa);hbKeyGb = 0;memset(&mem_64_b, 0, 0x40u);md5_4_plus5remainer4 = *((char *)md5_4 + 5) % 4;// 以下一连串的赋值是使 char_array_29_3 = md5_3, char_array_29_4 = md5_4char_array_29_3[0] = 0;*(_DWORD *)&char_array_29_3[1] = 0;*(_DWORD *)&char_array_29_3[5] = 0;*(_DWORD *)&char_array_29_3[9] = 0;*(_DWORD *)&char_array_29_3[13] = 0;*(_DWORD *)&char_array_29_3[17] = 0;*(_DWORD *)&char_array_29_3[21] = 0;*(_DWORD *)&char_array_29_3[25] = 0;v139 = 0;v140 = 0;char_array_29_4[0] = 0;*(_DWORD *)&char_array_29_4[1] = 0;*(_DWORD *)&char_array_29_4[5] = 0;*(_DWORD *)&char_array_29_4[9] = 0;*(_DWORD *)&char_array_29_4[13] = 0;*(_DWORD *)&char_array_29_4[17] = 0;*(_DWORD *)&char_array_29_4[21] = 0;*(_DWORD *)&char_array_29_4[25] = 0;v142 = 0;v143 = 0;*(_DWORD *)char_array_29_3 = *md5_3;*(_DWORD *)&char_array_29_3[4] = md5_3[1];*(_DWORD *)&char_array_29_3[8] = md5_3[2];*(_DWORD *)&char_array_29_3[12] = md5_3[3];*(_DWORD *)&char_array_29_3[16] = md5_3[4];*(_DWORD *)&char_array_29_3[20] = md5_3[5];*(_DWORD *)&char_array_29_3[24] = md5_3[6];*(_DWORD *)&char_array_29_3[28] = md5_3[7];*(_DWORD *)char_array_29_4 = *md5_4;*(_DWORD *)&char_array_29_4[4] = md5_4[1];*(_DWORD *)&char_array_29_4[8] = md5_4[2];*(_DWORD *)&char_array_29_4[12] = md5_4[3];*(_DWORD *)&char_array_29_4[16] = md5_4[4];*(_DWORD *)&char_array_29_4[20] = md5_4[5];*(_DWORD *)&char_array_29_4[24] = md5_4[6];*(_DWORD *)&char_array_29_4[28] = md5_4[7];v85 = md5_4_plus5remainer4;                   // 1v86 = abs(md5_4_plus5remainer4 - 5) % 4;      // 0v9 = (md5_4_plus5remainer4 + 2) % 4;          // 3v87 = (md5_4_plus5remainer4 + 2) % 4;         // 3v88 = abs(md5_4_plus5remainer4 - 3);          // 2v114[0] = 0;*(_DWORD *)&v114[1] = 0;*(_DWORD *)&v115[1] = 0;v116 = 0;v117 = 0;v118 = 0;v119 = 0;v120 = 0;v121 = 0;v122 = 0;v123[0] = 0;*(_DWORD *)&v123[1] = 0;*(_DWORD *)&v124[1] = 0;v125 = 0;v126 = 0;v127 = 0;v128 = 0;v129 = 0;v130 = 0;v131 = 0;*(_DWORD *)v114 = *(_DWORD *)&char_array_29_3[8 * md5_4_plus5remainer4];*(_DWORD *)v115 = *(_DWORD *)&char_array_29_3[8 * md5_4_plus5remainer4 + 4];*(_DWORD *)&v115[4] = *(_DWORD *)&char_array_29_4[8 * v86];*(int *)((char *)&v116 + 3) = *(_DWORD *)&char_array_29_4[8 * v86 + 4];*(int *)((char *)&v117 + 3) = *(_DWORD *)&char_array_29_3[8 * v9];*(int *)((char *)&v118 + 3) = *(_DWORD *)&char_array_29_3[8 * v9 + 4];*(int *)((char *)&v119 + 3) = *(_DWORD *)&char_array_29_4[8 * v88];*(int *)((char *)&v120 + 3) = *(_DWORD *)&char_array_29_4[8 * v88 + 4];*(_DWORD *)v123 = *(_DWORD *)&char_array_29_4[8 * md5_4_plus5remainer4];*(_DWORD *)v124 = *(_DWORD *)&char_array_29_4[8 * md5_4_plus5remainer4 + 4];*(_DWORD *)&v124[4] = *(_DWORD *)&char_array_29_3[8 * v86];*(int *)((char *)&v125 + 3) = *(_DWORD *)&char_array_29_3[8 * v86 + 4];*(int *)((char *)&v126 + 3) = *(_DWORD *)&char_array_29_4[8 * v9];*(int *)((char *)&v127 + 3) = *(_DWORD *)&char_array_29_4[8 * v9 + 4];*(int *)((char *)&v128 + 3) = *(_DWORD *)&char_array_29_3[8 * v88];*(int *)((char *)&v129 + 3) = *(_DWORD *)&char_array_29_3[8 * v88 + 4];v58 = (void *)md5_StrWithLength(v114, 32);    // 返回值 1ed63dc9a269d8705e297c03dcda7cf0// 为 6172e2fb2b28feeb02bfb5a58b9f3da4 的 md5v57 = (void *)md5_StrWithLength(v123, 32);    // 返回值 25928da86463ce9beba8110d2d514464// 为 b48c0cb916dffe4904fff6461bdb9b20 的 md5sprintf_s(&hbKeyGb, 0x41u, "%s%s", v58, v57); // hbKeyGb = "1ed63dc9a269d8705e297c03dcda7cf025928da86463ce9beba8110d2d514464"v43 = v58;j_j___free_base(v58);if ( v43 ){v58 = (void *)33059;v22 = 33059;}else{v22 = 0;}v42 = v57;j_j___free_base(v57);if ( v42 ){v57 = (void *)33059;v32 = 33059;}else{v32 = 0;}(*(void (**)(char *, const char *, ...))(*(_DWORD *)pThis + 4))(pThis, "[HBKEY] gb: %s", &hbKeyGb);if ( v95 % 2 )                                // 从反汇编中可看到 v95 为 hbkey_gb[7]{temp1 = 0;p_HbKeyGa = &hbKeyGa;pMem_64_a = &mem_64_a;p_HbKeyGa += strlen(p_HbKeyGa);lenHbKeyGa = ++p_HbKeyGa - &mem_64_a;len_HbKeyGa = p_HbKeyGa - &mem_64_a;while ( temp1 < len_HbKeyGa )               // 把 HbKeyGa 里面的小写字母全替换为大写{if ( *(&hbKeyGa + temp1) >= 97 && *(&hbKeyGa + temp1) <= 122 )*(&hbKeyGa + temp1) -= 32;++temp1;}}else{temp2 = 0;p_HbKeyGb = &hbKeyGb;pMem_64_b = &mem_64_b;p_HbKeyGb += strlen(p_HbKeyGb);lenHbKeyGb = ++p_HbKeyGb - &mem_64_b;len_HbKeyGb = p_HbKeyGb - &mem_64_b;while ( temp2 < len_HbKeyGb )               // 把 HbKeyGb 里面的小写字母全替换为大写{if ( *(&hbKeyGb + temp2) >= 97 && *(&hbKeyGb + temp2) <= 122 )*(&hbKeyGb + temp2) -= 32;++temp2;}}pHbKeyGa = &hbKeyGa;pHbKeyGb = &hbKeyGb;(*(void (**)(char *, const char *, ...))(*(_DWORD *)pThis + 4))(pThis, "[HBKEY] sga: %s", &hbKeyGa);(*(void (**)(char *, const char *, ...))(*(_DWORD *)pThis + 4))(pThis, "[HBKEY] sgb: %s", pHbKeyGb);hbKey = 0;memset(&v90, 0, 0x80u);if ( pHbKeyGb[9] % 2 ){index1 = 0;index2 = 0;index3 = 63;while ( index1 < 128 ){*(&hbKey + index1++) = pHbKeyGa[index2++];*(&hbKey + index1++) = pHbKeyGb[index3--];}}else{index4 = 0;index5 = 63;index6 = 0;while ( index4 < 128 ){*(&hbKey + index4++) = pHbKeyGa[index5--];*(&hbKey + index4++) = pHbKeyGb[index6++];}}(*(void (**)(char *, const char *, ...))(*(_DWORD *)pThis + 4))(pThis, "[HBKEY] key: %s", &hbKey);// hbKey = &"115e9d6643Fd6c391a32E6298dA8D70025Ae9269473c1053AdDc9dAa47Ec6f4092658912C89d9aB83644D6D32c0e898b2e2bCaF8B1E1F06d025dF5E184040654"sub_40EC40((void *)a2, &hbKey);v41 |= 1u;v146 = -1;std::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string<char,std::char_traits<char>,std::allocator<char>>(&a3);return a2;
}

上面的就是 AidcRes.generateKey 的整个流程,这个坑多并且复杂,简要说一下,具体看代码(b_Username_MonthDay 代指 'b177111122220517',不再赘述)

  1. 算出 b_Username_MonthDay,username_b_MonthDay,username_MonthDay_b,monthDay_Username_b 四个东西的 md5
  2. 根据 d5_b_Username_MonthDay[1] 的 ascii的奇偶性,重排四个 md5 的顺序并复制给四个变量,分别为 md5_1,md5_2,md5_3,md5_4,
  3. 此时会用到第二步的四个变量,根据他们的特定位来计算得出 hbkey_ga 与 hbkey_gb 的值
    • 根据 md5_1_pLus3remainder4 = *(char *)(md5_1 + 3) % 4; 这步的值取 md5_1 和 md5_2 排列算出 hbkey_ga
    • 根据 md5_4_plus5remainer4 = *((char *)md5_4 + 5) % 4; 这步的值取 md5_3 和 md5_4 排列算出 hbkey_gb
  4. 根据 hbkey_gb[7] 的 ascii,如果奇数就把 hbkey_ga 中的字母都大写,偶数就把 hbkey_gb 中的字母都大写
  5. 根据 hbkey_gb[9] 的 ascii 的奇偶性对 hbkey_ga 与 hbkey_gb 的值用简单算法进行重排,得到真实的 hbkey

这就是上面所有代码的大致流程,代码中我也有大量注释,大家可以看看。

总结

这个难点在分析算法上面,分析算法主要还是要靠动态调试,过程中遇到了很多很难的地方,参数和函数的重命名主要还是靠动态调试,
然后去猜测它的作用进行重命名。

这些文件我都保存了分析记录,大家可以跟着看看,总结如下

AidcComm.idb 看导出表可以看出是干嘛的,直接点进GetPWD即可看到我的分析
AidcRes.idb 里面也有我的分析,具体查看我改过的函数名 generateKey,然后 x 一下看调用地方
x32dbg_AidcRes.dd32 为我在用 x32dbg 分析AidcRes.exe的时候的记录,有一些我改过的函数名以及简要分析
简单的分析流程为 bp LoadLibrary,断到 AidcComm.dll,然后具体看eax和栈的变化,找到加密函数,再一层一层分析。

建议 ida 与 x32dbg 结合分析,最好起个 pppoe 服务器拦截账号密码协助分析,见我上一篇文章 PPPoE中间人拦截以及校园网突破漫谈中的代码。

调用流程为
AidcRes.generateKey(分析大头) --> AidcComm.GetRegularAccount --> AidcComm.GetPWD --> AidcComm.encryptPwdWithKey(分析大头,注意里面有个地方 f5 显示不出来,就是把一个key中的字母全大写的那部分,请结合汇编分析)

AidcRes.generateKey大致流程,这个坑多并且复杂,简要说一下,具体看代码
(b_Username_MonthDay 代指 'b177111122220517',不再赘述)

  1. 算出 b_Username_MonthDay,username_b_MonthDay,username_MonthDay_b,monthDay_Username_b 四个东西的 md5
  2. 根据 d5_b_Username_MonthDay[1] 的 ascii的奇偶性,重排四个 md5 的顺序并复制给四个变量
  3. 此时会用到第二步的四个变量,根据他们的特定位来计算得出 hbkey_ga 与 hbkey_gb 的值
  4. 根据 hbkey_gb[7] 的 ascii,如果奇数就把 hbkey_ga 中的字母都大写,偶数就把 hbkey_gb 中的字母都大写
  5. 根据 hbkey_gb[9] 的 ascii 的奇偶性对 hbkey_ga 与 hbkey_gb 的值用简单算法进行重排,得到真实的 hbkey

AidcComm.encryptPwdWithKey大致流程

  1. password 用 key RC4 一下得到 A
  2. 把 A md5 一下得到 B,如果第 11 位为奇数,取 B 的前 16 位,偶数就后 16 位,得到 C
  3. C 再用 key RC4 一下得到 D
  4. D 再 md5 一下,取 [8:24]得到 E
  5. E[今天几号日期 % 16] 替换为 'b' 得到最后的密码

为了防止被商业利用,就不公开逆向得出的加密脚本了,喜欢折腾校园网的可以自行根据本文摸索。

分析文件打包

  • 飞Young宽带_带分析.7z

转载于:https://www.cnblogs.com/Akkuman/p/11163273.html

湖北校园网PC端拨号算法逆向相关推荐

  1. 【Android 逆向】Frida 框架 ( 安装 frida 12.7.5 | 安装 frida-tools 5.1.0 | PC 端 frida 与 安卓模拟器端 frida-server )

    文章目录 一.安装 frida 12.7.5 二.安装 frida-tools 5.1.0 三.PC 端 frida 与 安卓模拟器端 frida-server 一.安装 frida 12.7.5 前 ...

  2. 【Android 逆向】Android 逆向通用工具开发 ( PC 端工程分析 | 网络初始化操作 | PC 端工程核心业务逻辑 )

    文章目录 前言 一.网络初始化操作 二.PC 端工程核心业务逻辑 三.博客资源 前言 本篇博客重点分析 PC 端 hacktool 模块 ; 一.网络初始化操作 HackCommand::Prepar ...

  3. 【Android 逆向】Android 逆向通用工具开发 ( adb forward 网络端口重定向命令 | PC 端逆向程序主函数分析 )

    文章目录 前言 一.adb forward 网络端口重定向命令 二.PC 端逆向程序主函数分析 前言 本篇博客重点分析 PC 端 hacktool 模块 ; 一.adb forward 网络端口重定向 ...

  4. 【AI PC端算法优化】一,一步步优化RGB转灰度图算法

    欢迎关注AI PC端算法优化代码库:https://github.com/BBuf/Image-processing-algorithm-Speed . 0. 资源获取 公众号输入 高性能计算 关键词 ...

  5. 【AI PC端算法优化】二,一步步优化自然饱和度算法

    上一节的RGB转灰度图算法我又做了两个相关优化,加入了多线程以及去掉了上次SSE计算中的一些重复计算,现在相对于传统实现已经可以获得4倍加速.同时我也在做一个AVX2的优化,所以不久后我将发布一个RG ...

  6. PC 端微信逆向分析

    关键字: 微信.duilib库hook,duilib模拟点击. 最近有朋友问我libcef如何注入js,然后又谈到微信用了libcef云云. 捣腾了一下午,知道怎么注入js后,发现朋友是需要auto ...

  7. [小程序逆向]PC端VX小程序代码提取

    前言 在微信 PC 端还未上线小程序功能之前,想要提取 VC 小程序代码必须通过移动端来提取,不过现在有了 PC 端之后可以方便的在 PC 上使用小程序,那么也可以通过 PC 端来获取 VX 小程序代 ...

  8. 项目实战-PC端固定布局【2】认识网页大纲算法(HTML5 Outliner)

    注: body,nav,section需要标题 head,div不需要标题 链接: https://gsnedders.html5.org/outliner/ 步骤:选择文件--->Outlin ...

  9. 微信协议分析 pc端记录

    android端的之前参考如下帖子: https://blog.csdn.net/yy405145590/article/details/79963999 但是这个帖子出来之后,微信在pack之后又封 ...

最新文章

  1. FPGA最全科普总结
  2. 最近的生活[发点牢骚]
  3. 【POJ】【2449】Remmarguts' Date
  4. 【408预推免复习】计算机网络(谢希仁第七版)第四章——网络层
  5. mongodb 聚合 分组查询
  6. vscode 调试python 无法连接远程服务器_vscode 远程调试python的方法
  7. 为数据计算提供强力引擎,阿里云文件存储HDFS v1.0公测发布
  8. php的mcypt,php 7.3 在Centos6.x下的安装过程
  9. linux mkdir 系统调用,Linux Rootkit 系列四:对于系统调用挂钩方法的补充
  10. PAT1061. 判断题
  11. numpy与pandas各种功能及其对比(超全)
  12. SQL Server数据同步的研究(单向/双向)
  13. 宋宝华:谈一谈Linux写时拷贝(COW)的安全漏洞(1)
  14. 分享一个办公环境文件共享服务器软件CuteHttpFileServer
  15. 嵌入式ARM核心板介绍
  16. 计算机萌新适合学安卓,老学姐呕心沥血整理的大学必备的软件!萌新赶紧收藏...
  17. mybaitis-plus 持久层高效开发, 懒人神器
  18. 执行 taro init myApp 报错 无法加载文件 C:\Users\Administrator\AppData\Roaming\npm\taro.ps1
  19. jakarta-taglibs的使用说明
  20. SOA为什么不“香”了?| 建设数据中台系列(三)

热门文章

  1. 来自同济子豪兄的无私分享-关于YOLOv1模型的学习(一)
  2. Javacript中父节点、子节点、兄节点的简单用法[0306]
  3. 电动汽车,绝缘检测方法
  4. 国密加密解密之vue-sm2使用
  5. Android中的MVVM架构设计-实用篇(五)实现RecyclerView列表展示
  6. 使用QML自绘页面导航条
  7. 《程序员面试金典(第6版)》面试题 08.14. 布尔运算(动态规划,分治,递归,难度hard++)
  8. 自定义滑条封装含有百分比例显示(swift版)
  9. 云IDE:Code-Server:VS Code的开源IDE
  10. E-office OA 平行越权漏洞复现