某校园网客户端软件分析(一)

客户端同目录有一个config.ini文件

[Parameters]
LatestUsername=13788888888
LatestPassword=TxMJCxEc

OD载入搜索字符串找到 LatestUsername 回车进入 下个断 一步一步走可以知道解密函数

0041F368  |.  8D4D C4       lea ecx,[local.15]
0041F36B  |.  E8 E068FEFF   call NiWiFiAs.00405C50
0041F370  |.  50            push eax                                 ; |ReturnBuffer = 00000001
0041F371  |.  68 0CB65B00   push NiWiFiAs.005BB60C                   ; |Default = ""
0041F376  |.  68 FCEB5B00   push NiWiFiAs.005BEBFC                   ; |LatestPassword
0041F37B  |.  68 14EA5B00   push NiWiFiAs.005BEA14                   ; |Parameters
0041F380  |.  FF15 28A65B00 call dword ptr ds:[<&KERNEL32.GetPrivate>; \GetPrivateProfileStringA
0041F386  |.  3BF4          cmp esi,esp
0041F388  |.  E8 B37A1100   call NiWiFiAs.00536E40
0041F38D  |.  6A FF         push -0x1
0041F38F  |.  8D4D C4       lea ecx,[local.15]
0041F392  |.  E8 A9AAFEFF   call NiWiFiAs.00409E40
0041F397  |.  8D4D C4       lea ecx,[local.15]
0041F39A  |.  E8 6161FEFF   call NiWiFiAs.00405500
0041F39F  |.  50            push eax
0041F3A0  |.  8D85 60FFFFFF lea eax,[local.40]
0041F3A6  |.  50            push eax
0041F3A7  |.  E8 4476FFFF   call NiWiFiAs.004169F0                   ;  解密call
0041F3AC  |.  83C4 08       add esp,0x8
0041F3AF  |.  85C0          test eax,eax
0041F3B1  |.  74 1E         je short NiWiFiAs.0041F3D1

解密call如下

004169F9  |.  53            push ebx
004169FA  |.  56            push esi
004169FB  |.  57            push edi
004169FC  |.  8DBD 04FFFFFF lea edi,[local.63]
00416A02  |.  B9 3F000000   mov ecx,0x3F
00416A07  |.  B8 CCCCCCCC   mov eax,0xCCCCCCCC
00416A0C  |.  F3:AB         rep stos dword ptr es:[edi]
00416A0E  |.  C745 F8 00000>mov [local.2],0x0
00416A15  |.  C745 EC 00000>mov [local.5],0x0
00416A1C  |.  C745 E0 00000>mov [local.8],0x0
00416A23  |.  C745 D4 00000>mov [local.11],0x0
00416A2A  |.  C745 C8 00000>mov [local.14],0x0
00416A31  |.  EB 09         jmp short NiWiFiAs.00416A3C
00416A33  |>  8B45 E0       /mov eax,[local.8]
00416A36  |.  83C0 01       |add eax,0x1
00416A39  |.  8945 E0       |mov [local.8],eax
00416A3C  |>  8B45 0C        mov eax,[arg.2]
00416A3F  |.  0345 E0       |add eax,[local.8]
00416A42  |.  0FBE08        |movsx ecx,byte ptr ds:[eax]             ;  获取字符
00416A45  |.  85C9          |test ecx,ecx
00416A47  |.  0F84 F5000000 |je NiWiFiAs.00416B42
00416A4D  |.  8B45 0C       |mov eax,[arg.2]
00416A50  |.  0345 E0       |add eax,[local.8]
00416A53  |.  0FBE08        |movsx ecx,byte ptr ds:[eax]
00416A56  |.  83F9 3D       |cmp ecx,0x3D
00416A59  |.  75 18         |jnz short NiWiFiAs.00416A73
00416A5B  |.  8B45 C8       |mov eax,[local.14]
00416A5E  |.  83C0 01       |add eax,0x1
00416A61  |.  8945 C8       |mov [local.14],eax
00416A64  |.  837D C8 02    |cmp [local.14],0x2
00416A68  |.  7E 07         |jle short NiWiFiAs.00416A71
00416A6A  |.  33C0          |xor eax,eax
00416A6C  |.  E9 41010000   |jmp NiWiFiAs.00416BB2
00416A71  |>  EB 51         |jmp short NiWiFiAs.00416AC4
00416A73  |>  C745 EC 00000>|mov [local.5],0x0
00416A7A  |.  EB 09         |jmp short NiWiFiAs.00416A85
00416A7C  |>  8B45 EC       |/mov eax,[local.5]
00416A7F  |.  83C0 01       ||add eax,0x1
00416A82  |.  8945 EC       ||mov [local.5],eax
00416A85  |>  8B45 EC       | mov eax,[local.5]
00416A88  |.  0FB688 58D45B>||movzx ecx,byte ptr ds:[eax+0x5BD458]   ;  ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
00416A8F  |.  85C9          ||test ecx,ecx
00416A91  |.  74 1B         ||je short NiWiFiAs.00416AAE
00416A93  |.  8B45 EC       ||mov eax,[local.5]
00416A96  |.  0FB688 58D45B>||movzx ecx,byte ptr ds:[eax+0x5BD458]   ;  ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
00416A9D  |.  8B55 0C       ||mov edx,[arg.2]
00416AA0  |.  0355 E0       ||add edx,[local.8]
00416AA3  |.  0FBE02        ||movsx eax,byte ptr ds:[edx]
00416AA6  |.  3BC8          ||cmp ecx,eax
00416AA8  |.  75 02         ||jnz short NiWiFiAs.00416AAC
00416AAA  |.  EB 02         ||jmp short NiWiFiAs.00416AAE
00416AAC  |>^ EB CE         |\jmp short NiWiFiAs.00416A7C
00416AAE  |>  837D EC 40    |cmp [local.5],0x40
00416AB2  |.  75 07         |jnz short NiWiFiAs.00416ABB
00416AB4  |.  33C0          |xor eax,eax
00416AB6  |.  E9 F7000000   |jmp NiWiFiAs.00416BB2
00416ABB  |>  8B45 F8       |mov eax,[local.2]
00416ABE  |.  0345 EC       |add eax,[local.5]
00416AC1  |.  8945 F8       |mov [local.2],eax
00416AC4  |>  8B45 E0       |mov eax,[local.8]
00416AC7  |.  25 03000080   |and eax,0x80000003
00416ACC  |.  79 05         |jns short NiWiFiAs.00416AD3
00416ACE  |.  48            |dec eax
00416ACF  |.  83C8 FC       |or eax,-0x4
00416AD2  |.  40            |inc eax
00416AD3  |>  83F8 03       |cmp eax,0x3
00416AD6  |.  75 5C         |jnz short NiWiFiAs.00416B34
00416AD8  |.  8B45 F8       |mov eax,[local.2]
00416ADB  |.  C1E8 10       |shr eax,0x10
00416ADE  |.  8B4D 08       |mov ecx,[arg.1]
00416AE1  |.  034D D4       |add ecx,[local.11]
00416AE4  |.  8801          |mov byte ptr ds:[ecx],al                ;  位或前密码转换
00416AE6  |.  8B55 D4       |mov edx,[local.11]
00416AE9  |.  83C2 01       |add edx,0x1
00416AEC  |.  8955 D4       |mov [local.11],edx
00416AEF  |.  837D C8 02    |cmp [local.14],0x2
00416AF3  |.  7D 17         |jge short NiWiFiAs.00416B0C
00416AF5  |.  8B45 F8       |mov eax,[local.2]
00416AF8  |.  C1E8 08       |shr eax,0x8
00416AFB  |.  8B4D 08       |mov ecx,[arg.1]
00416AFE  |.  034D D4       |add ecx,[local.11]
00416B01  |.  8801          |mov byte ptr ds:[ecx],al
00416B03  |.  8B55 D4       |mov edx,[local.11]
00416B06  |.  83C2 01       |add edx,0x1
00416B09  |.  8955 D4       |mov [local.11],edx
00416B0C  |>  837D C8 01    |cmp [local.14],0x1
00416B10  |.  7D 14         |jge short NiWiFiAs.00416B26
00416B12  |.  8B45 08       |mov eax,[arg.1]
00416B15  |.  0345 D4       |add eax,[local.11]
00416B18  |.  8A4D F8       |mov cl,byte ptr ss:[ebp-0x8]
00416B1B  |.  8808          |mov byte ptr ds:[eax],cl
00416B1D  |.  8B55 D4       |mov edx,[local.11]
00416B20  |.  83C2 01       |add edx,0x1
00416B23  |.  8955 D4       |mov [local.11],edx
00416B26  |>  C745 F8 00000>|mov [local.2],0x0
00416B2D  |.  C745 C8 00000>|mov [local.14],0x0
00416B34  |>  8B45 F8       |mov eax,[local.2]                       ;  计算
00416B37  |.  C1E0 06       |shl eax,0x6
00416B3A  |.  8945 F8       |mov [local.2],eax
00416B3D  |.^ E9 F1FEFFFF   \jmp NiWiFiAs.00416A33
00416B42  |>  8B45 E0       mov eax,[local.8]
00416B45  |.  25 03000080   and eax,0x80000003
00416B4A  |.  79 05         jns short NiWiFiAs.00416B51
00416B4C  |.  48            dec eax
00416B4D  |.  83C8 FC       or eax,-0x4
00416B50  |.  40            inc eax
00416B51  |>  85C0          test eax,eax
00416B53  |.  75 12         jnz short NiWiFiAs.00416B67
00416B55  |.  68 A0D45B00   push NiWiFiAs.005BD4A0                   ;  ~!:?$*<(qw2e5o7i8x12c6m67s98w43d2l45we82q3iuu1z4xle23rt4oxclle34e54u6r8m
00416B5A  |.  E8 61711200   call NiWiFiAs.0053DCC0
00416B5F  |.  83C4 04       add esp,0x4
00416B62  |.  3B45 D4       cmp eax,[local.11]
00416B65  |.  7D 04         jge short NiWiFiAs.00416B6B
00416B67  |>  33C0          xor eax,eax
00416B69  |.  EB 47         jmp short NiWiFiAs.00416BB2
00416B6B  |>  C745 E0 00000>mov [local.8],0x0
00416B72  |.  EB 09         jmp short NiWiFiAs.00416B7D
00416B74  |>  8B45 E0       /mov eax,[local.8]
00416B77  |.  83C0 01       |add eax,0x1
00416B7A  |.  8945 E0       |mov [local.8],eax
00416B7D  |>  8B45 E0        mov eax,[local.8]
00416B80  |.  3B45 D4       |cmp eax,[local.11]
00416B83  |.  7D 1F         |jge short NiWiFiAs.00416BA4
00416B85  |.  8B45 E0       |mov eax,[local.8]
00416B88  |.  0FBE88 A0D45B>|movsx ecx,byte ptr ds:[eax+0x5BD4A0]    ;  ~!:?$*<(qw2e5o7i8x12c6m67s98w43d2l45we82q3iuu1z4xle23rt4oxclle34e54u6r8m
00416B8F  |.  8B55 08       |mov edx,[arg.1]
00416B92  |.  0355 E0       |add edx,[local.8]
00416B95  |.  0FBE02        |movsx eax,byte ptr ds:[edx]
00416B98  |.  33C1          |xor eax,ecx
00416B9A  |.  8B4D 08       |mov ecx,[arg.1]
00416B9D  |.  034D E0       |add ecx,[local.8]
00416BA0  |.  8801          |mov byte ptr ds:[ecx],al
00416BA2  |.^ EB D0         \jmp short NiWiFiAs.00416B74
00416BA4  |>  8B45 08       mov eax,[arg.1]
00416BA7  |.  0345 D4       add eax,[local.11]
00416BAA  |.  C600 00       mov byte ptr ds:[eax],0x0
00416BAD  |.  B8 01000000   mov eax,0x1
00416BB2  |>  5F            pop edi                                  ;  0019D1A8
00416BB3  |.  5E            pop esi                                  ;  0019D1A8
00416BB4  |.  5B            pop ebx                                  ;  0019D1A8
00416BB5  |.  81C4 FC000000 add esp,0xFC
00416BBB  |.  3BEC          cmp ebp,esp
00416BBD  |.  E8 7E021200   call NiWiFiAs.00536E40
00416BC2  |.  8BE5          mov esp,ebp
00416BC4  |.  5D            pop ebp                                  ;  0019D1A8
00416BC5  \.  C3            retn

根据代码执行和分析可以看出来
每次取加密后的密码一次取四位
按ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
前三位逻辑是取出密码与A的相对位置然后与之前的计算累计 累计后乘以2的6次方也就是64
最后一位直接累加不乘64算出来之后的数字按十六进制的顺序位置在~!:?$*<(qw2e5o7i8x12c6m67s98w43d2l45we82q3iuu1z4xle23rt4oxclle34e54u6r8m表中相应字符的ascii进行异或例如

第一位与 ~

第二位与 !

第三位与 : 以此类推等等
——————————————————————————————————————————
修复密码含有==的解密
如果密码存在=则乘以64 但如果最后一位为=不乘
以及如果十六进制最后为00则消除
——————————————————————————————————————————
最后附上源码

#include <iostream>
#include <string>
#include <cmath>
using namespace std;
int Crackpass(string ThreePass);
string GetPass(string Hexstring);
string TenToHex(int n);
string ChaPass(string TwPass, int num);
int main()
{
    string RawPass, ResPass;
    cin >> RawPass;
    for (size_t knum = 0; knum < RawPass.length(); knum += 4)
    {
        ResPass += TenToHex(Crackpass(RawPass.substr(knum, 4)));
    }
    while (ResPass[ResPass.length() - 1] == '0'&&ResPass[ResPass.length() - 2] == '0')
    {
        ResPass = ResPass.substr(0, ResPass.length() - 2);
    }
    cout << ResPass << endl;
    cout <<"{" +GetPass(ResPass)+"}";
    cin.get();
    cin.get();
    return 0;
}
int Crackpass(string ThreePass)
{
    string stastrp = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    long  Res = 0;
    int rnum = 0;
    for (int num = 0; num < 4; num++)
    {
        char chs = ThreePass[num];
        if (chs != '=')
        {
            for (rnum = 0; stastrp[rnum] != chs; rnum++);
            Res += rnum;
        }
        if (num == 3) break;
        Res *= 64;
    }
    return Res;
}

string TenToHex(int n) {
    string s = "00000000", res = s;
    int a, i = 0, k;
    do {
        a = n & 15;//取后四位的二进制位 
        n >>= 4;//n右移四位 
        n &= 0xffffffff;
        s[i] = (a <= 9) ? a + 48 : a + 55;
        i++;
    } while (n);
    for (k = i - 1; k >= 0; k--)
        for (int tem = s.length(); tem != 0; tem--)
        {
            res[tem - 1] = s[s.length() - tem];
        }
    res = res.substr(2, 6);
    return res;
}

string GetPass(string Hexstring)
{
    string Ress;
    for (size_t knum = 0; knum < Hexstring.length(); knum += 2)
    {
        Ress += ChaPass(Hexstring.substr(knum, 2), ((knum + 2) / 2));
    }
    return Ress;
}
string ChaPass(const string TwPass, int num)
{
    int num1;
    string ress;
    char res = { 0 };
    string rain = "~!:?$*<(qw2e5o7i8x12c6m67s98w43d2l45we82q3iuu1z4xle23rt4oxclle34e54u6r8m";
    sscanf(TwPass.c_str(), "%x", &num1);

    res = int(rain[num - 1]) ^ num1;
    ress = res;

    return ress;
}


成果

更新代码 提高简洁度

#include <iostream>
#include <string>
using namespace std;
string calpass(const string &);
int main()
{
    string lastpass;
    cin >> lastpass;
    cout<<calpass(lastpass);
    system("pause");
    return 0;
}
string calpass(const string &pass)
{
    static int numcal = 0;
    static string charlist = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    static string passlist = "~!:?$*<(qw2e5o7i8x12c6m67s98w43d2l45we82q3iuu1z4xle23rt4oxclle34e54u6r8m";
    string retpass = "";
    unsigned int startcal = 0,passcal=0;
    for (unsigned calnum = 0; calnum < pass.length();calnum++)
    {
        int test = 0;
        int num = 0;

        startcal++;
        if (pass[calnum] != '=')
        {
            while (pass[calnum] != charlist[num])
                num++;
            passcal += num;
        }

        if (startcal == 4)
        {
            test = (passcal & 0xff0000)>>16;        
            retpass += test ^ passlist[numcal++];

            test = (passcal & 0x00ff00)>>8;
            retpass += test ^ passlist[numcal++];

            if(test = (passcal & 0x0000ff)>>0)
            retpass += test ^ passlist[numcal++];

            passcal=startcal = 0;

        }
        else
            passcal *= 64;
    }
    return retpass;
}

留下评论