首页
社区
课程
招聘
[原创]追赶高校生之 - 2016腾讯的游戏安全竞赛题PC第一题
发表于: 2016-3-18 02:13 6654

[原创]追赶高校生之 - 2016腾讯的游戏安全竞赛题PC第一题

2016-3-18 02:13
6654
逆了一遍,要达到腾讯要求的高校生水准还是不容易。。

#include <stdio.h>
#include <windows.h>

char sample_str[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@%";

int Get_Index_in_sample(UCHAR ch)
{
    char *p = (char*)memchr(sample_str, ch, sizeof(sample_str)-1);
    if (p)
        return (int)(p - sample_str);
    else
        return -1;
}

int UserName(PLONG UserNameArray)
{
    char chUserName[] = "zxxttrrun";
    ULONG UserNameLen = (ULONG)strlen(chUserName);
    char tmp[25] = {0};
    ULONG *v7;
    ULONG i;

    if ( (unsigned int)(UserNameLen - 6) > 0xE )
        return -1;

    for (i = 0; i < 16; i++)
    {
        v7 = (ULONG*)&tmp[i];
        *v7 += UserNameLen * (i + 20160126) * chUserName[i % UserNameLen];
    }

    for ( i = 0; i < 20; i += 4 )
    {
        UserNameArray[i/4] = (*(LONG *)&tmp[i]) / 10;
    }

    return 0;
}

int Password(PULONG PasswordArray)
{
    char PasswordBuf[100] = "JVeFMIdiy5HLoQcSzMzMzMzMzMz";
    ULONG PasswordLen = 27;
    ULONG tmpDWORD;
    PUCHAR p = (PUCHAR)&tmpDWORD;
    ULONG i;
    ULONG j;
    UCHAR tmp[25] = {0};
    PUCHAR p1 = tmp;

    for (i = 0, j = 0; i < PasswordLen; i++)
    {
        char ch = PasswordBuf[i];

        if ( !isalnum(ch) && ch != '@' && ch != '%' )
            break;

        p[i%4] = ch;

        if(j++ == 3)
        {
            for ( j = 0; j < 4; j++ )
            {
                p[j] = Get_Index_in_sample(p[j]);
            }

            *p1++ = (p[0]<<2) + ((p[1] >> 4) & 3);
            *p1++ = (p[1] << 4) ^ ((p[2] >> 2) & 0xF);
            *p1++ = (p[2] << 6) + p[3];
            j = 0;
        }
    }

    if (j)
    {
        memset((char *)&tmpDWORD + j, 0, 4 - j);

        for ( j = 0; j < 4; j++ )
        {
            p[j] = Get_Index_in_sample(p[j]);
        }

        *p1++ = (p[0]<<2) + ((p[1] >> 4) & 3);
        *p1++ = (p[1] << 4) ^ ((p[2] >> 2) & 0xF);
        *p1++ = (p[2] << 6) + p[3];
    }

    for ( i = 0; i < 20; i += 4 )
    {
        PasswordArray[i/4] = *(ULONG *)&tmp[i];
    }

    return 0;
}

int main()
{
    LONG U[5];  // 逆向过程是算数右移,所以必须是有符号数
    ULONG P[5];

    UserName(U);
    Password(P);

    if ( P[4] + U[0] == P[2]     &&
         P[2] + U[1] == P[4] * 2 &&
         P[3] + U[2] == P[0]     &&
         P[0] + U[3] == P[3] * 2 &&
         P[1] + U[4] == U[2] * 3)
    {
        printf("注册成功~\n");
    }
    else
        printf("注册失败!\n");

    return 0;
}

[课程]Android-CTF解题方法汇总!

上传的附件:
收藏
免费 3
支持
分享
最新回复 (11)
雪    币: 284
活跃值: (3394)
能力值: ( LV5,RANK:75 )
在线值:
发帖
回帖
粉丝
2
void Keygen()
{
    LONG U[5];  // 逆向过程是算数右移,所以必须是有符号数
    ULONG P[5];
    PUCHAR c = (PUCHAR)P;
    UCHAR mm[28] = {0};
    ULONG i;
    ULONG j = 0;

    UserName(U);

    P[0] = U[2] * 2 + U[3];
    P[1] = U[2] * 3 - U[4];
    P[2] = U[0] * 2 + U[1];
    P[3] = U[2] + U[3];
    P[4] = U[0] + U[1];

    for (i = 0; i < 20; i += 3)
    {
        mm[j++] =   c[i] >> 2;
        mm[j++] = ((c[i] & 3) << 4) + (c[i+1] >> 4);
        mm[j++] = ((c[i+1] & 0xF) << 2) + ((c[i+2] & 0xC0) >> 6);
        mm[j++] =   c[i+2] & 0x3F;
    }

    for (i = 0; i < 27; i++)
    {
        mm[i] = sample_str[mm[i]];
    }
    mm[i] = 0;

    printf("Your Key : %s\n", mm);
}
2016-3-18 16:13
0
雪    币: 44229
活跃值: (19965)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
3
建议把附件上传一份。
2016-3-18 18:05
0
雪    币: 284
活跃值: (3394)
能力值: ( LV5,RANK:75 )
在线值:
发帖
回帖
粉丝
4
已上传IDB文件
2016-3-18 18:56
0
雪    币: 90
活跃值: (91)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
感谢分享,版区有你更精彩!
2016-3-18 20:39
0
雪    币: 163
活跃值: (103)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
6
我已经达到标准。
2016-3-18 22:32
0
雪    币: 229
活跃值: (89)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
7
*p1++ = (p[0]<<2) + ((p[1] >> 4) & 3);
            *p1++ = (p[1] << 4) ^ ((p[2] >> 2) & 0xF);
            *p1++ = (p[2] << 6) + p[3];
这个部分我也推到出来了,但是,你个算法的逆运算我该怎么写呢?对照着汇编反着写一回?还是怎么弄,就是这里卡着我啦
2016-3-21 14:50
0
雪    币: 284
活跃值: (3394)
能力值: ( LV5,RANK:75 )
在线值:
发帖
回帖
粉丝
8
[QUOTE=daowang;1421218]*p1++ = (p[0]<<2) + ((p[1] >> 4) & 3);
            *p1++ = (p[1] << 4) ^ ((p[2] >> 2) & 0xF);
            *p1++ = (p[2] << 6) + p[3];
这个部分我也推到出来了,但是,你...[/QUOTE]

看2楼Keygen.
2016-3-21 14:56
0
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
这题是啥?给程序然后逆向出源码吗?
2016-3-21 15:15
0
雪    币: 229
活跃值: (89)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
10
为什么会这样,我就是不知道怎么弄成那样的呀,完全不是加密算法的,逆算法
2016-3-22 19:31
0
雪    币: 229
活跃值: (89)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
11
我知道了,存在一个位数丢失问题,逆向时候还是没有吧算法看懂啊
2016-3-22 20:15
0
雪    币: 284
活跃值: (3394)
能力值: ( LV5,RANK:75 )
在线值:
发帖
回帖
粉丝
12
是啊,在对密码字符从sample_str里取index的时候,由于sample_str只有0x40个,刚好用6个2进制位表示,也就是这个转换后的值只有6个bit是有效的,最高位2bit始终为0
2016-3-23 12:48
0
游客
登录 | 注册 方可回帖
返回
//