A&D1

IsDebugger Present

原理


​ 反调试,该API查询PEB结构中的IsDebugger标志位, 未调试返回0,调试状态返回1。

绕过


  1. nop指令

    1
    2
    mov rax ; IsDebuggerPresent
    call rax ; IsDebuggerPresent
  2. jnz和jz


    jnz在结果不为0时跳转,jz在结果为0时跳转

    1
    2
    3
    4
    5
    6
    7
    8
    sub_4019F4()
    {
    return ISDebuggerPresent;
    }
    if(!sub_4019F4)
    {
    puts();
    }

    这个时候如果处于调试状态,返回1,不会执行put,这时候只需要去汇编指令处把jnz改为jz,重新汇编后会变成

    1
    2
    3
    4
    5
    6
    7
    8
    sub_4019F4()
    {
    return ISDebuggerPresent;
    }
    if(sub_4019F4)
    {
    puts();
    }

    3.Attach to process

    1
    2
    3
    sub_4019F4();
    printf("%d",n);
    scanf("%d",&m);

    可以先让程序运行,这时候已经步过了反调试函数,然后Attach to process就可以调试了

    4.修改EIP:jump、call、ret指令

多线程

  1. 函数介绍

    1
    2
    3
    1 CreateThread 创建线程
    2 CloseHandle 关闭线程
    3 WaitForSingleObject() 实现线程转换

​ 2.题目——Youngter drive

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int __cdecl main_0(int argc, const char **argv, const char **envp)
{
HANDLE v4; // [esp+D0h] [ebp-14h]
HANDLE hObject; // [esp+DCh] [ebp-8h]

((void (*)(void))sub_4110FF)();
::hObject = CreateMutexW(0, 0, 0);
j_strcpy(Destination, &Source);
hObject = CreateThread(0, 0, StartAddress, 0, 0, 0);
v4 = CreateThread(0, 0, sub_41119F, 0, 0, 0);
CloseHandle(hObject);
CloseHandle(v4);
while ( dword_418008 != -1 )
;
sub_411190();
CloseHandle(::hObject);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void __stdcall StartAddress_0(int a1)
{
while ( 1 )
{
WaitForSingleObject(hObject, 0xFFFFFFFF);
if ( dword_418008 > -1 )
{
sub_41112C(&Source, dword_418008);
--dword_418008;
Sleep(0x64u);
}
ReleaseMutex(hObject);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
void __stdcall sub_411B10(int a1)
{
while ( 1 )
{
WaitForSingleObject(hObject, 0xFFFFFFFF);
if ( dword_418008 > -1 )
{
Sleep(0x64u);
--dword_418008;
}
ReleaseMutex(hObject);
}
}

实际上就是每隔两位对数组元素做一次处理

Z3

  1. 基础

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    1 声明整数x = Int('x')
    2 声明实数x = Real('x')
    3 声明布尔类型x = Bool('x')

    1 创建solver求解器
    例:s = Solver()
    2 添加约束条件
    例:s.add(x+y==10)
    3 检查solver中的约束是否满足
    例:s.check()
    4 利用model()输出运算结果
    例:s.model()

    2.题目——Universe_final_answer

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    __int64 __fastcall main(int a1, char **a2, char **a3)
    {
    char v4[32]; // [rsp+0h] [rbp-A8h] BYREF
    char input[104]; // [rsp+20h] [rbp-88h] BYREF
    unsigned __int64 v6; // [rsp+88h] [rbp-20h]

    v6 = __readfsqword(0x28u);
    __printf_chk(1LL, "Please give me the key string:", a3);
    scanf("%s", input);
    if ( sub_860(input) )
    {
    sub_C50(input, v4);
    __printf_chk(1LL, "Judgement pass! flag is actf{%s_%s}\n", input);
    }
    else
    {
    puts("False key!");
    }
    return 0LL;
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    bool __fastcall sub_860(char *input)
    {
    int v1; // ecx
    int v2; // esi
    int v3; // edx
    int v4; // er9
    int v5; // er11
    int v6; // ebp
    int v7; // ebx
    int v8; // er8
    int v9; // er10
    bool result; // al
    int v11; // [rsp+0h] [rbp-38h]

    v1 = input[1];
    v2 = *input;
    v3 = input[2];
    v4 = input[3];
    v5 = input[4];
    v6 = input[6];
    v7 = input[5];
    v8 = input[7];
    v9 = input[8];
    result = 0;
    if ( -85 * v9 + 58 * v8 + 97 * v6 + v7 + -45 * v5 + 84 * v4 + 95 * v2 - 20 * v1 + 12 * v3 == 12613 )
    {
    v11 = input[9];
    if ( 30 * v11 + -70 * v9 + -122 * v6 + -81 * v7 + -66 * v5 + -115 * v4 + -41 * v3 + -86 * v1 - 15 * v2 - 30 * v8 == -54400
    && -103 * v11 + 120 * v8 + 108 * v7 + 48 * v4 + -89 * v3 + 78 * v1 - 41 * v2 + 31 * v5 - (v6 << 6) - 120 * v9 == -10283
    && 71 * v6 + (v7 << 7) + 99 * v5 + -111 * v3 + 85 * v1 + 79 * v2 - 30 * v4 - 119 * v8 + 48 * v9 - 16 * v11 == 22855
    && 5 * v11 + 23 * v9 + 122 * v8 + -19 * v6 + 99 * v7 + -117 * v5 + -69 * v3 + 22 * v1 - 98 * v2 + 10 * v4 == -2944
    && -54 * v11 + -23 * v8 + -82 * v3 + -85 * v2 + 124 * v1 - 11 * v4 - 8 * v5 - 60 * v7 + 95 * v6 + 100 * v9 == -2222
    && -83 * v11 + -111 * v7 + -57 * v2 + 41 * v1 + 73 * v3 - 18 * v4 + 26 * v5 + 16 * v6 + 77 * v8 - 63 * v9 == -13258
    && 81 * v11 + -48 * v9 + 66 * v8 + -104 * v6 + -121 * v7 + 95 * v5 + 85 * v4 + 60 * v3 + -85 * v2 + 80 * v1 == -1559
    && 101 * v11 + -85 * v9 + 7 * v6 + 117 * v7 + -83 * v5 + -101 * v4 + 90 * v3 + -28 * v1 + 18 * v2 - v8 == 6308 )
    {
    result = 99 * v11 + -28 * v9 + 5 * v8 + 93 * v6 + -18 * v7 + -127 * v5 + 6 * v4 + -9 * v3 + -93 * v1 + 58 * v2 == -1697;
    }
    }
    return result;
    }

    脚本

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    from z3 import*

    s=Solver()
    v1=Int('v1')
    v2=Int('v2')
    v3=Int('v3')
    v4=Int('v4')
    v5=Int('v5')
    v6=Int('v6')
    v7=Int('v7')
    v8=Int('v8')
    v9=Int('v9')
    v11=Int('v11')

    s.add(-85 * v9 + 58 * v8 + 97 * v6 + v7 + -45 * v5 + 84 * v4 + 95 * v2 - 20 * v1 + 12 * v3 == 12613)
    s.add(-85 * v9 + 58 * v8 + 97 * v6 + v7 + -45 * v5 + 84 * v4 + 95 * v2 - 20 * v1 + 12 * v3 == 12613)
    s.add(-103 * v11 + 120 * v8 + 108 * v7 + 48 * v4 + -89 * v3 + 78 * v1 - 41 * v2 + 31 * v5 - (v6 *64) - 120 * v9 == -10283)
    s.add(71 * v6 + (v7 *128) + 99 * v5 + -111 * v3 + 85 * v1 + 79 * v2 - 30 * v4 - 119 * v8 + 48 * v9 - 16 * v11 == 22855)
    s.add(5 * v11 + 23 * v9 + 122 * v8 + -19 * v6 + 99 * v7 + -117 * v5 + -69 * v3 + 22 * v1 - 98 * v2 + 10 * v4 == -2944)
    s.add(-54 * v11 + -23 * v8 + -82 * v3 + -85 * v2 + 124 * v1 - 11 * v4 - 8 * v5 - 60 * v7 + 95 * v6 + 100 * v9 == -2222)
    s.add(-83 * v11 + -111 * v7 + -57 * v2 + 41 * v1 + 73 * v3 - 18 * v4 + 26 * v5 + 16 * v6 + 77 * v8 - 63 * v9 == -13258)
    s.add(81 * v11 + -48 * v9 + 66 * v8 + -104 * v6 + -121 * v7 + 95 * v5 + 85 * v4 + 60 * v3 + -85 * v2 + 80 * v1 == -1559)
    s.add(101 * v11 + -85 * v9 + 7 * v6 + 117 * v7 + -83 * v5 + -101 * v4 + 90 * v3 + -28 * v1 + 18 * v2 - v8 == 6308)
    s.add(99 * v11 + -28 * v9 + 5 * v8 + 93 * v6 + -18 * v7 + -127 * v5 + 6 * v4 + -9 * v3 + -93 * v1 + 58 * v2 == -1697)

    if s.check()==sat:
    result=s.model()

    print(result)

    这里的移位操作不能被识别,需要手动转换。

    其实这道题带了个简单的混淆

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    unsigned __int64 __fastcall sub_C50(const char *a1, _BYTE *a2)
    {
    size_t v4; // rax
    unsigned int v5; // edx
    int v6; // edi
    int v7; // ecx
    __int64 v8; // r8
    __int128 *v9; // rsi
    unsigned int v10; // ecx
    int v11; // eax
    int v12; // edi
    int v13; // edx
    int v14; // eax
    _BYTE *v15; // rsi
    _BYTE *v16; // rcx
    _BYTE *v17; // r8
    int *i; // rax
    unsigned __int64 result; // rax
    __int128 v20[2]; // [rsp+0h] [rbp-48h] BYREF
    __int64 v21; // [rsp+20h] [rbp-28h]
    unsigned __int64 v22; // [rsp+28h] [rbp-20h]

    v22 = __readfsqword(0x28u);
    v20[0] = 0LL;
    v21 = 0LL;
    v20[1] = 0LL;
    v4 = strlen(a1);
    v5 = 0;
    v6 = 9;
    while ( v5 < v4 )
    {
    v7 = a1[v5++];
    v6 ^= v7;
    }
    if ( v6 )
    {
    v8 = 0LL;
    v9 = v20;
    while ( 1 )
    {
    v9 = (__int128 *)((char *)v9 + 4);
    v10 = v8 + 1;
    v11 = v6 / 10;
    v12 = v6 % 10;
    *((_DWORD *)v9 - 1) = v12;
    LOBYTE(v13) = v12;
    v6 = v11;
    if ( !v11 )
    break;
    v8 = v10;
    }
    v14 = v8 - 1;
    v15 = a2;
    v16 = &a2[v10];
    v17 = &a2[v8];
    for ( i = (int *)v20 + v14; ; --i )
    {
    *v15 = v13 + 48;
    if ( v17 == v15 )
    break;
    v13 = *i;
    ++v15;
    }
    }
    else
    {
    v16 = a2;
    }
    result = __readfsqword(0x28u) ^ v22;
    *v16 = 0;
    return result;
    }

    这里面的函数没有对输入进行处理,所以不用管

修改二进制文件汇编指令

1.题目——Overlong

运行程序,得到

1
2
I never broke the encoding:

1
2
3
4
5
6
7
8
9
10
11
int __stdcall start(int a1, int a2, int a3, int a4)
{
CHAR Text[128]; // [esp+0h] [ebp-84h] BYREF
int v6; // [esp+80h] [ebp-4h]

v6 = sub_401160(Text, &unk_402008, 28);
Text[v6] = 0;
MessageBoxA(0, Text, Caption, 0);
return 0;
}

这里只取出了TEXT的前28位,而程序运行后的输出长度正好是28,加上题目overlong提示和:结尾,猜测部分长度没显示

所以需要修改二进制文件汇编指令

1
2
3
4
5
6
7
.text:004011C0                 push    ebp
.text:004011C1 mov ebp, esp
.text:004011C3 sub esp, 84h
.text:004011C9 push 1Ch
.text:004011CB push offset unk_402008
.text:004011D0 lea eax, [ebp+Text]

1c对应28,所以需要将1c改大

1、ida修改–> 点击菜单项“Edit”–“Patch program”–“Assemble” --> 点击菜单项“Edit”–“Patch program”–“Apply patches to input file”,在弹出的对话框中点击OK按钮,则成功完成指令修改。

点击确认按钮时,可能会弹出无法写入对话框,只需去除该文件的只读属性,再次执行第三步即可。

2、OD修改–>根据汇编指令定位–>右键–>二进制–>编辑 ,其他的可以直接修改指令,但是这里修改之后后面的汇编代码全变了,虽然不知道为啥。

3、winhex修改–>定位——先去ida的patch byte找到push 1c对应6A 1C 68 08 20 40 00 8D 85 7C FF FF FF 50 E8 84–>去winhex修改1c,然后重新保存运行

RSA

1、题目——Signin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
__int64 __fastcall main(int a1, char **a2, char **a3)
{
char v4[16]; // [rsp+0h] [rbp-4A0h] BYREF
char v5[16]; // [rsp+10h] [rbp-490h] BYREF
char v6[16]; // [rsp+20h] [rbp-480h] BYREF
char v7[16]; // [rsp+30h] [rbp-470h] BYREF
char v8[112]; // [rsp+40h] [rbp-460h] BYREF
char v9[1000]; // [rsp+B0h] [rbp-3F0h] BYREF
unsigned __int64 v10; // [rsp+498h] [rbp-8h]

v10 = __readfsqword(0x28u);
puts("[sign in]");
printf("[input your flag]: ");
__isoc99_scanf("%99s", v8);
sub_96A(v8, v9);//加密函数直接linux远调就可以知道是转十六进制数;
__gmpz_init_set_str(v7, "ad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35", 16LL);//十六进制
__gmpz_init_set_str(v6, v9, 16LL);
__gmpz_init_set_str(v4, "103461035900816914121390101299049044413950405173712170434161686539878160984549", 10LL);//十进制
__gmpz_init_set_str(v5, "65537", 10LL);
__gmpz_powm(v6, v6, v5, v4);
if ( (unsigned int)__gmpz_cmp(v6, v7) )
puts("GG!");
else
puts("TTTTTTTTTTql!");
return 0LL;
}

看到65537,加上查了__gmpz_powm()函数,也相当于__mpz_powm()函数,可以判断这是rsa加密

1
2
3
void mpz_powm (mpz_t rop, const mpz_t base, const mpz_t exp, const mpz_t mod) [Function]
Set rop to base^exp mod mod.

其实就是计算 base 的 exp 次方,并对 mod 取模,最后将结果写入 rop 中

剩下的就是解出p、q,然后写脚本了

1
2
3
4
5
6
7
8
C=M^E mod N
C是密文,M是明文,E是公钥(E和 φ(N)互为质数),N是公共模数(质数 PQ相乘得到N),MOD就是模运算
M=C^D mod N

DE * D % φ(N) = 1
φ(N) = (P-1)(Q-1)


2、rsa

题目给出了公钥和flag.enc文件

1
2
(N,e)是公钥, (N, d)是私钥

公钥和密钥生成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
4.1N
我们准备两个很小对质数,
p17
q19
Npq323

4.2L
Llcmp1q1)= lcm(1618) = 144
1441618对最小公倍数

4.3E
E必须要满足2个条件:1 < E < LgcdEL=1
1 < E < 144gcdE144) = 1 #gcd,最大公因数
E144互为质数,5显然满足上述2个条件
E5 此时公钥=(EN)= (5323

4.4D
D也必须满足2个条件:1 < D < LED mod L1
1 < D < 1445D mod 1441
显然当D29 时满足上述两个条件
1 < 29 < 144
529 mod 144145 mod 1441
此时私钥=(DN)=(29323

私钥和公钥都可以拿去解析

这里解析得到

1
2
3
4
5
e = 65537
n=86934482296048119190666062003494800588905656017203025617216654058378322103517(n拿去分解)
p = 285960468890451637935629440372639283459
q = 304008741604601924494328155975272418463

从文件读取公钥或者私钥

1
2
3
4
with open('private.pem', mode='rb') as privatefile:
keydata = privatefile.read()#rb 是以二进制形式打开文件
privkey = rsa.PrivateKey.load_pkcs1(keydata)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import gmpy2 
import rsa

e = 65537
n = 86934482296048119190666062003494800588905656017203025617216654058378322103517
p = 285960468890451637935629440372639283459
q = 304008741604601924494328155975272418463

phin = (q-1)*(p-1)

d = gmpy2.invert(e, phin)

key = rsa.PrivateKey(n, e, int(d), p, q)#生成私钥

with open("D:\\new\\题目\\output\\flag.enc", "rb+") as f:
f = f.read()
print(rsa.decrypt(f, key))


Maze

Maze题一般都需要找到入口、出口还有移动方向

题目——unctf20201—easymaze

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 *v3; // rax
char *v4; // rdi
unsigned __int64 v5; // rbx
const char *v6; // rdx
int v7; // eax
int v8; // er9
int v9; // er8
int v10; // edx
char v11; // cl
int v12; // ecx
int v13; // ecx
__int64 *v14; // rax

sub_1400011A0(argc, argv, envp);
dword_140006790[0] = 1;#把鼠标放上去显示int型
dword_140006794 = 1;
dword_1400067B4 = 1;
dword_1400067CC = 1;
dword_1400067EC = 1;
dword_1400067F0 = 1;
dword_1400067D4 = 1;
dword_1400067D8 = 1;
dword_1400067F8 = 1;
dword_140006810 = 1;
dword_14000682C = 1;
dword_140006844 = 1;
dword_140006840 = 1;
dword_140006864 = 1;
dword_140006868 = 1;
dword_140006884 = 1;
dword_1400068A0 = 1;
dword_1400068BC = 1;
dword_1400068DC = 1;
dword_14000689C = 1;
v3 = sub_140001800(std::cout, (__int64)"Plz inpu7 the P4th :");
std::ostream::operator<<(v3, sub_1400019D0);
v4 = input;
v5 = -1i64;
sub_140001AA0(std::cin, -1i64, input);
do
++v5;
while ( input[v5] );
if ( v5 > 0x11 )
{
v6 = "to0 lon9!t0o long!";
goto LABEL_26;
}
if ( v5 < 0x11 )
{
v6 = (const char *)&unk_140003770;
goto LABEL_26;
}
v7 = dword_140006710;
v8 = 0;
v9 = dword_140006714;
v10 = dword_140006710;
do
{
v11 = *v4;
if ( *v4 == 'A' )
goto LABEL_21;
if ( v11 == 'W' )
{
++v10;
v12 = v7 % 2;
++v7;
goto LABEL_20;
}
if ( v11 == 'E' )
{
++v10;
v13 = v7 % 2;
++v7;
LABEL_16:
dword_140006710 = v7;
if ( v13 )
goto LABEL_23;
goto LABEL_17;
}
if ( v11 != 'D' )
{
if ( v11 != 'X' )
{
if ( v11 != 'Z' )
{
v6 = "What the fuck did you give me?";
goto LABEL_26;
}
--v10;
v12 = v7 % 2;
--v7;
LABEL_20:
dword_140006710 = v7;
if ( !v12 )
goto LABEL_23;
LABEL_21:
--v9;
goto LABEL_22;
}
--v10;
v13 = v7 % 2;
--v7;
goto LABEL_16;
}
LABEL_17:
++v9;
LABEL_22:
dword_140006714 = v9;
LABEL_23:
++v8;
++v4;
}
while ( v8 < v5 );
v6 = "Congratulations on this forced to get the right flag, you entered is the correct answer!";

if ( dword_140006790[7 * v7 + v9] != 1 )

v6 = "Try it again little unlucky!";
LABEL_26:
v14 = sub_140001800(std::cout, (__int64)v6);
std::ostream::operator<<(v14, sub_1400019D0);
return 0;
}

动调就可以把AWEDXZ的移动弄出来

在ida里面dd表示四个字节,db表示一个字节

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
data:00007FF673BF6794 dword_7FF673BF6794 dd 0                 ; DATA XREF: main+27↑w
.data:00007FF673BF6798 dd 0
.data:00007FF673BF679C db 0
.data:00007FF673BF679D db 0
.data:00007FF673BF679E db 0
.data:00007FF673BF679F db 0
.data:00007FF673BF67A0 db 0
.data:00007FF673BF67A1 db 0
.data:00007FF673BF67A2 db 0
.data:00007FF673BF67A3 db 0
.data:00007FF673BF67A4 db 0
.data:00007FF673BF67A5 db 0
.data:00007FF673BF67A6 db 0
.data:00007FF673BF67A7 db 0

要对着db按D转换数据类型,全部转为int型

base64变表

1、base64变表实际上就是将base64编码表进行了修改

2、题目——nctf2021 shadowbringer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v4[16]; // [rsp+20h] [rbp-60h] BYREF
char v5[15]; // [rsp+30h] [rbp-50h] BYREF
char v6; // [rsp+3Fh] [rbp-41h] BYREF
char v7[16]; // [rsp+40h] [rbp-40h] BYREF
char v8[16]; // [rsp+50h] [rbp-30h] BYREF
char v9[16]; // [rsp+60h] [rbp-20h] BYREF
char v10[32]; // [rsp+70h] [rbp-10h] BYREF

_main();
youknowwhat();
std::string::string((std::string *)v5);
std::allocator<char>::allocator(&v6);
std::string::string(v4, "U>F2UsQXN`5sXMELT=:7M_2<X]^1ThaWF0=KM?9IUhAsTM5:T==_Ns&<Vhb!", &v6);
std::allocator<char>::~allocator(&v6);
std::operator<<<std::char_traits<char>>(printf_0, "Welcome.Please input your flag:\n");
std::operator>><char>(scanf, (std::string *)v5);
std::string::string((std::string *)v8, (const std::string *)v5);

Emet(v7, v8);

std::string::operator=(v5, v7);
std::string::~string((std::string *)v7);
std::string::~string((std::string *)v8);
std::string::string((std::string *)v10, (const std::string *)v5);

Selch(v9, v10);

std::string::operator=(v5, v9);
std::string::~string((std::string *)v9);
std::string::~string((std::string *)v10);
if ( (unsigned __int8)std::operator==<char>(v5, v4) )
std::operator<<<std::char_traits<char>>(printf_0, "Right.");
else
std::operator<<<std::char_traits<char>>(printf_0, "Wrong.");
std::string::~string((std::string *)v4);
std::string::~string((std::string *)v5);
return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
std::string *__fastcall Emet(std::string *a1, std::string *a2)
{
int i; // ebx
char *v3; // rax
unsigned __int64 v4; // rax
int j; // ebx
unsigned int v6; // eax
char *v7; // rax
unsigned __int64 v9; // [rsp+20h] [rbp-90h] BYREF
char v10; // [rsp+2Eh] [rbp-82h] BYREF
char v11; // [rsp+2Fh] [rbp-81h] BYREF
char v12[16]; // [rsp+30h] [rbp-80h] BYREF
char v13[16]; // [rsp+40h] [rbp-70h] BYREF
char v14[16]; // [rsp+50h] [rbp-60h] BYREF
char v15[16]; // [rsp+60h] [rbp-50h] BYREF
char v16[16]; // [rsp+70h] [rbp-40h] BYREF
char v17[16]; // [rsp+80h] [rbp-30h] BYREF
char v18[16]; // [rsp+90h] [rbp-20h] BYREF
char v19[16]; // [rsp+A0h] [rbp-10h] BYREF

std::allocator<char>::allocator(&v10);
std::string::string(&v9, &unk_48A000, &v10);
std::allocator<char>::~allocator(&v10);
std::allocator<char>::allocator(&v11);
std::string::string(a1, &unk_48A000, &v11);
std::allocator<char>::~allocator(&v11);
for ( i = 0; i < (unsigned __int64)std::string::size(a2); ++i )
{
v3 = (char *)std::string::operator[](a2, i);
std::bitset<8ull>::bitset(v14, (unsigned int)*v3);
std::bitset<8ull>::to_string(v13, v14);
std::operator+<char>(v12, &v9, v13);
std::string::operator=(&v9, v12);
std::string::~string((std::string *)v12);
std::string::~string((std::string *)v13);
}
while ( 1 )
{
v4 = std::string::size((std::string *)&v9);
if ( v4 == 6 * (v4 / 6) )
break;
std::operator+<char>(v15, &v9, 48i64);
std::string::operator=(&v9, v15);
std::string::~string((std::string *)v15);
}
for ( j = 0; j < (unsigned __int64)std::string::size((std::string *)&v9); j += 6 )
{
std::string::substr((std::string *)v18, (unsigned __int64)&v9, j);
std::bitset<6ull>::bitset<char,std::char_traits<char>,std::allocator<char>>(v17, v18, 0i64);
v6 = std::bitset<6ull>::to_ulong(v17);
v7 = (char *)std::string::operator[](&hisoralce, v6);
std::operator+<char>(v16, a1, (unsigned int)*v7);
std::string::operator=(a1, v16);
std::string::~string((std::string *)v16);
std::string::~string((std::string *)v18);
}
while ( (std::string::size(a1) & 3) != 0 )
{
std::operator+<char>(v19, a1, 33i64);
std::string::operator=(a1, v19);
std::string::~string((std::string *)v19);
}
std::string::~string((std::string *)&v9);
return a1;
}

这里的j+=6,像是base64,而&hisorale是指针

1
2
3
4
5
6
7
8
9
10
bss:00000000004AA030 hisoralce db  28h ; (                   ; DATA XREF: youknowwhat(void)+2A↑o
.bss:00000000004AA030 ; youknowwhat(void)+40↑o ...
.bss:00000000004AA031 db 3Dh ; =
.bss:00000000004AA032 db 0BBh
.bss:00000000004AA033 db 0
.bss:00000000004AA034 db 0
.bss:00000000004AA035 db 0
.bss:00000000004AA036 db 0
.bss:00000000004AA037 db 0

需要对着db按d转换类型,才能看到该地址存储的内容