BUUCTF在线评测 (buuoj.cn)
放到ida,进入func函数
int func()
{
int result; // eax
int v1[4]; // [esp+14h] [ebp-44h]
unsigned __int8 v2; // [esp+24h] [ebp-34h] BYREF
unsigned __int8 v3; // [esp+25h] [ebp-33h]
unsigned __int8 v4; // [esp+26h] [ebp-32h]
unsigned __int8 v5; // [esp+27h] [ebp-31h]
unsigned __int8 v6; // [esp+28h] [ebp-30h]
int v7; // [esp+29h] [ebp-2Fh]
int v8; // [esp+2Dh] [ebp-2Bh]
int v9; // [esp+31h] [ebp-27h]
int v10; // [esp+35h] [ebp-23h]
unsigned __int8 v11; // [esp+39h] [ebp-1Fh]
char v12[29]; // [esp+3Bh] [ebp-1Dh] BYREF
strcpy(v12, "Qsw3sj_lz4_Ujw@l");
printf("Please input:");
scanf("%s", &v2);
result = v2;
if ( v2 == 65 )
{
result = v3;
if ( v3 == 67 )
{
result = v4;
if ( v4 == 84 )
{
result = v5;
if ( v5 == 70 )
{
result = v6;
if ( v6 == 123 )
{
result = v11;
if ( v11 == 125 )
{
v1[0] = v7;
v1[1] = v8;
v1[2] = v9;
v1[3] = v10;
*&v12[17] = 0;
while ( *&v12[17] <= 15 )\\0~15的循环
{
if ( *(v1 + *&v12[17]) > 64 && *(v1 + *&v12[17]) <= 90 )\\如果flag[i]是大写字母
*(v1 + *&v12[17]) = (*(v1 + *&v12[17]) - 51) % 26 + 65;
if ( *(v1 + *&v12[17]) > 96 && *(v1 + *&v12[17]) <= 122 )\\如果flag[i]是小写字母
*(v1 + *&v12[17]) = (*(v1 + *&v12[17]) - 79) % 26 + 97;
++*&v12[17];
}
*&v12[17] = 0;
while ( *&v12[17] <= 15 )\\0~15的循环
{
result = v12[*&v12[17]];
if ( *(v1 + *&v12[17]) != result )\\result里存的是flag,一个对比操作
return result;
++*&v12[17];
}
return printf("You are correct!");
}
}
}
}
}
}
return result;
}
清楚逻辑了,写个脚本
v15= [ 'Q','s','w','3','s','j', '_','l','z','4','_','U','j','w','@','l' ]
flag=""
for i in range(16):
for j in range(128):#ascii表上有127个字符,一个一个试叫做爆破,用devc爆破更快
x=j
if 'A'<=chr(x)<='Z':
x=(x-51)%26+65
if 'a'<=chr(x)<='z':
x=(x-79)%26+97
if chr(x)==v15[i]:
flag+=chr(j)
print ('flag{'+flag+'}')
Python 字符串str详解(超详细)_在idle中定义字符串变量str1,赋值为“黄沙百战穿金甲,不破楼兰终不还。”,完成以下操作: (1-CSDN博客
flag{Cae3ar_th4_Gre@t}
打开是个网页,查看源代码
找到程序,变灰的部分是关键,是指如果是前13个字母就加13,如果是后13个字母就减13
写个脚本
flag="PyvragFvqrYbtvafNerRnfl@syner-ba.pbz"
f=''
for i in flag:
if 'A'<=i<='M' or 'a'<=i<='m':
k=chr(ord(i)+13)
elif 'N'<=i<='Z' or 'n'<=i<='z':
k=chr(ord(i)-13)
else:
k=i
f+=''.join(k)
print(f)
#flag{ClientSideLoginsAreEasy@flare-on.com}
放到ida
这是下载的文本
逻辑比较简单,写个脚本
p=[198,232,816,200,1536,300,6144,984,51200,570,92160,1200,565248,756,1474560,800,6291456,1782,65536000]
for i in range(1,20):
if (i & 1) != 0 :
p[i-1]=chr(p[i-1] >> i)
else:
p[i-1]=chr((int)(p[i-1]/i)) #浮点型转一下整型
a=''
a=''.join(p)
print(a)
#ctf2020{d9-dE6-20c}
有壳
脱一下
查看字符串
主函数
进入4009AE看一下
看到这我们知道要用z3模块求解了
from z3 import *
s = Solver()
a1 = [0]*32
for i in range(32):
a1[i] = Int('a1['+str(i)+']')
s.add( 1629056 * a1[0] == 166163712 )
s.add( 6771600 * a1[1] == 731332800 )
s.add( 3682944 * a1[2] == 357245568 )
s.add( 10431000 * a1[3] == 1074393000 )
s.add( 3977328 * a1[4] == 489211344 )
s.add( 5138336 * a1[5] == 518971936 )
s.add( 7532250 * a1[7] == 406741500 )
s.add( 5551632 * a1[8] == 294236496 )
s.add( 3409728 * a1[9] == 177305856 )
s.add( 13013670 * a1[10] == 650683500 )
s.add( 6088797 * a1[11] == 298351053 )
s.add( 7884663 * a1[12] == 386348487 )
s.add( 8944053 * a1[13] == 438258597 )
s.add( 5198490 * a1[14] == 249527520 )
s.add( 4544518 * a1[15] == 445362764 )
s.add( 3645600 * a1[17] == 174988800 )
s.add( 10115280 * a1[16] == 981182160 )
s.add( 9667504 * a1[18] == 493042704 )
s.add( 5364450 * a1[19] == 257493600 )
s.add( 13464540 * a1[20] == 767478780 )
s.add( 5488432 * a1[21] == 312840624 )
s.add( 14479500 * a1[22] == 1404511500 )
s.add( 6451830 * a1[23] == 316139670 )
s.add( 6252576 * a1[24] == 619005024 )
s.add( 7763364 * a1[25] == 372641472 )
s.add( 7327320 * a1[26] == 373693320 )
s.add( 8741520 * a1[27] == 498266640 )
s.add( 8871876 * a1[28] == 452465676 )
s.add( 4086720 * a1[29] == 208422720 )
s.add( 9374400 * a1[30] == 515592000 )
s.add(5759124 * a1[31] == 719890500)
s.check()
print(s.model())
输出结果:
[a1[23] = 49,
a1[26] = 51,
a1[24] = 99,
a1[11] = 49,
a1[0] = 102,
a1[30] = 55,
a1[21] = 57,
a1[1] = 108,
a1[16] = 97,
a1[18] = 51,
a1[3] = 103,
a1[13] = 49,
a1[20] = 57,
a1[7] = 54,
a1[31] = 125,
a1[29] = 51,
a1[10] = 50,
a1[4] = 123,
a1[2] = 97,
a1[8] = 53,
a1[12] = 49,
a1[25] = 48,
a1[14] = 48,
a1[28] = 51,
a1[22] = 97,
a1[17] = 48,
a1[15] = 98,
a1[19] = 48,
a1[9] = 52,
a1[5] = 101,
a1[27] = 57]
再写个脚本
a1 = [0]*32
a1[31] = 125
a1[30] = 55
a1[29] = 51
a1[28] = 51
a1[27] = 57
a1[26] = 51
a1[25] = 48
a1[24] = 99
a1[23] = 49
a1[22] = 97
a1[21] = 57
a1[20] = 57
a1[19] = 48
a1[18] = 51
a1[16] = 97
a1[17] = 48
a1[15] = 98
a1[14] = 48
a1[13] = 49
a1[12] = 49
a1[11] = 49
a1[10] = 50
a1[9] = 52
a1[8] = 53
a1[7] = 54
a1[5] = 101
a1[4] = 123
a1[3] = 103
a1[2] = 97
a1[1] = 108
a1[0] = 102
for i in range(32):
if i == 6:
continue
print(chr(a1[i]), end="")
flag{e65421110ba03099a1c039337}
a1[6]作者忘加了,自己把26个字母和数字依次代到a1[6]里尝试提交,试完a1[6]在第二个位置
flag{e165421110ba03099a1c039337}
f12查看字符串,找到关键字符串
跳转过去,点黄色的部分再跳转
f5反汇编
分析一下
开头就是三个字符串,我们推测这三个字符串是连在一起的,因为后面有个循环是36次,这三个字符串加起来长度也是36
__int64 sub_4009C6()
{
__int64 result; // rax
int i; // [rsp+Ch] [rbp-114h]
__int64 v2; // [rsp+10h] [rbp-110h]
__int64 v3; // [rsp+18h] [rbp-108h]
__int64 v4; // [rsp+20h] [rbp-100h]
__int64 v5; // [rsp+28h] [rbp-F8h]
__int64 v6; // [rsp+30h] [rbp-F0h]
__int64 v7; // [rsp+38h] [rbp-E8h]
__int64 v8; // [rsp+40h] [rbp-E0h]
__int64 v9; // [rsp+48h] [rbp-D8h]
__int64 v10; // [rsp+50h] [rbp-D0h]
__int64 v11; // [rsp+58h] [rbp-C8h]
char v12[13]; // [rsp+60h] [rbp-C0h] BYREF
char v13[4]; // [rsp+6Dh] [rbp-B3h] BYREF
char v14[19]; // [rsp+71h] [rbp-AFh] BYREF
char v15[32]; // [rsp+90h] [rbp-90h] BYREF
int v16; // [rsp+B0h] [rbp-70h]
char v17; // [rsp+B4h] [rbp-6Ch]
char v18[72]; // [rsp+C0h] [rbp-60h] BYREF
unsigned __int64 v19; // [rsp+108h] [rbp-18h]
v19 = __readfsqword(0x28u);
qmemcpy(v12, "Iodl>Qnb(ocy", 12);
v12[12] = 127;
qmemcpy(v13, "y.i", 3);
v13[3] = 127;
qmemcpy(v14, "d`3w}wek9{iy=~yL@EC", sizeof(v14));
memset(v15, 0, sizeof(v15));
v16 = 0;
v17 = 0;
sub_4406E0(0LL, v15, 37LL);
v17 = 0;
if ( sub_424BA0(v15) == 36 )
{
for ( i = 0; i < (unsigned __int64)sub_424BA0(v15); ++i )
{
if ( (unsigned __int8)(v15[i] ^ i) != v12[i] )
{
result = 4294967294LL;
goto LABEL_13;
}
}
sub_410CC0("continue!");
memset(v18, 0, 65);
sub_4406E0(0LL, v18, 64LL);
v18[39] = 0;
if ( sub_424BA0(v18) == 39 )
{
v2 = sub_400E44(v18);
v3 = sub_400E44(v2);
v4 = sub_400E44(v3);
v5 = sub_400E44(v4);
v6 = sub_400E44(v5);
v7 = sub_400E44(v6);
v8 = sub_400E44(v7);
v9 = sub_400E44(v8);
v10 = sub_400E44(v9);
v11 = sub_400E44(v10);
if ( !(unsigned int)sub_400360(v11, off_6CC090) )
{
sub_410CC0("You found me!!!");
sub_410CC0("bye bye~");
}
result = 0LL;
}
else
{
result = 4294967293LL;
}
}
else
{
result = 0xFFFFFFFFLL;
}
LABEL_13:
if ( __readfsqword(0x28u) != v19 )
sub_444020();
return result;
}
写个脚本爆破一下,这里v[12]12和v[13]3是数字,我在python中写\127,爆破的结果不对,而写十六进制的\x7f就可以,爆破的结果只得到一条信息,然而并不是真正的flag
p='Iodl>Qnb(ocy\x7fy.i\x7fd`3w}wek9{iy=~yL@EC'
flag1 = []
for i in range(36):
for key in range(32, 127):
if chr(key ^ i) == p[i] :
flag1.append(chr(key))
print(''.join(flag1))
#Info:The first four chars are `flag`
再往下看,又是一个循环,我们点进sub_400E44函数
sub_410CC0("continue!");
memset(v18, 0, 65);
sub_4406E0(0LL, v18, 64LL);
v18[39] = 0;
if ( sub_424BA0(v18) == 39 )
{
v2 = sub_400E44(v18);
v3 = sub_400E44(v2);
v4 = sub_400E44(v3);
v5 = sub_400E44(v4);
v6 = sub_400E44(v5);
v7 = sub_400E44(v6);
v8 = sub_400E44(v7);
v9 = sub_400E44(v8);
v10 = sub_400E44(v9);
v11 = sub_400E44(v10);
if ( !(unsigned int)sub_400360(v11, off_6CC090) )
{
sub_410CC0("You found me!!!");
sub_410CC0("bye bye~");
}
有点复杂,进入黄色的部分看看
一看到这一串,我们可以猜到是base64加密,且加密了10次,我们找找是对什么进行了加密
加密完是个循环,里面有个函数,猜测是个比较的函数,括号里是用来比较的两个字符串,看看第二个字符串是什么
sub_410CC0("continue!");
memset(v18, 0, 65);
sub_4406E0(0LL, v18, 64LL);
v18[39] = 0;
if ( sub_424BA0(v18) == 39 )
{
v2 = sub_400E44(v18);
v3 = sub_400E44(v2);
v4 = sub_400E44(v3);
v5 = sub_400E44(v4);
v6 = sub_400E44(v5);
v7 = sub_400E44(v6);
v8 = sub_400E44(v7);
v9 = sub_400E44(v8);
v10 = sub_400E44(v9);
v11 = sub_400E44(v10);
if ( !(unsigned int)sub_400360(v11, off_6CC090) )
{
sub_410CC0("You found me!!!");
sub_410CC0("bye bye~");
}
我们点进去,一直找到源头,是一大串字符,看字符串的最后是两个等号,这也是base64加密的一个标志,我们对它进行10次base64解密
是个网址,进去看看
是篇文章,这是作者把理论运用到题目里了啊
我们再往下找,发现没啥有用信息了,但是我们刚找字符串的时候是不是在字符串的下面发现了可疑的字符,点进去看一看
分析一下
unsigned __int64 sub_400D35()
{
unsigned __int64 result; // rax
unsigned int v1; // [rsp+Ch] [rbp-24h]
int i; // [rsp+10h] [rbp-20h]
int j; // [rsp+14h] [rbp-1Ch]
unsigned int v4; // [rsp+24h] [rbp-Ch]
unsigned __int64 v5; // [rsp+28h] [rbp-8h]
v5 = __readfsqword(0x28u);
v1 = sub_43FD20(0LL) - qword_6CEE38;
for ( i = 0; i <= 1233; ++i )
{
sub_40F790(v1);
sub_40FE60();
sub_40FE60();
v1 = sub_40FE60() ^ 0x98765432;
}
v4 = v1; // 上面都没用
if ( ((unsigned __int8)v1 ^ byte_6CC0A0[0]) == 102 && (HIBYTE(v4) ^ (unsigned __int8)a0x56) == 103 )// v1等于v4,相当于v1第一个和最后一个和byte_6CC0A0这个数组的第一个和第四个异或,异或完的是f和g,猜测这个是v1这四个字母分别与byte_6CC0A0前四位异或完是flag。
前面第一条信息说前四个字符是flag,这里也可以知道v1是4个字符
为什么v1会是一个数组呢,因为HIBYTE()函数的作用是获取高字节也就是数组的最后一位,同时还有BYTE()、BYTE1()、BYTE2()第一个是获取数组的第一位,第二个就是获取第二位,依次类推。
// 逆向异或可以得到v1数组也就是v4数组
{
for ( j = 0; j <= 24; ++j )
sub_410E90((unsigned __int8)(byte_6CC0A0[j] ^ *((_BYTE *)&v4 + j % 4)));// 这是让byte_6CC0A0与v4数组循环异或,抑或完的就是flag
}
result = __readfsqword(0x28u) ^ v5;
if ( result )
sub_444020();
return result;
}
写个脚本,得到flag
key2=[0x40,0x35,0x20,0x56,0x5D,0x18,0x22,0x45,0x17,0x2F,0x24,0x6E,0x62,0x3C,0x27,0x54,0x48,0x6C,0x24,0x6E,0x72,0x3C,0x32,0x45,0x5B]
key3='flag'
key4=[]
flag=[]
for x in range(4):
key4.append(chr(key2[x] ^ ord(key3[x])))
print(key4)
for i in range(25):
flag.append(chr(key2[i]^ord(key4[i%4])))
print(''.join(flag))
#flag{Act1ve_Defen5e_Test}
放到ida,先看一下字符串
找到主函数
int __cdecl main(int argc, const char **argv, const char **envp)
{
char Str[104]; // [rsp+20h] [rbp-70h] BYREF
int j; // [rsp+88h] [rbp-8h]
int i; // [rsp+8Ch] [rbp-4h]
sub_402230(argc, argv, envp);
sub_40E640("Give me your code:\n");
sub_40E5F0("%s", Str);
if ( strlen(Str) != 33 )
{
sub_40E640("Wrong!\n");
system("pause");
exit(0);
}
for ( i = 0; i <= 32; ++i )
{
byte_414040[i] = Str[dword_40F040[i]]; #把dword_40F040的数据变成字符型形式给byte_414040
byte_414040[i] ^= LOBYTE(dword_40F040[i]); # LOBYTE是取16bit数据的低8bit,这里是一个打乱顺序的操作,这是通过观察dword_40F040的数据发现正好是0~32的乱序猜测的(别的文章说的)
}
for ( j = 0; j <= 32; ++j )
{
if ( byte_40F0E0[j] != byte_414040[j] )#一个对比操作,对byte_40F0E0进行逆向即可
{
sub_40E640("Wrong!\n");
system("pause");
exit(0);
}
}
sub_40E640("Right!Good Job!\n");
sub_40E640("Here is your flag: %s\n", Str);
system("pause");
return 0;
}
对LOWORD, HIWORD, LOBYTE, HIBYTE的理解_mfc中lobyte-CSDN博客
这里8dup(0)是存8个0
汇编: dup伪指令_year db 4 dup('0')-CSDN博客
写个脚本
dword_40F040 = [0x9, 0x0A, 0x0F, 0x17, 0x7, 0x18, 0x0C, 0x6, 0x1, 0x10, 0x3, 0x11, 0x20, 0x1D, 0x0B, 0x1E, 0x1B, 0x16, 0x4, 0x0D, 0x13, 0x14, 0x15, 0x2, 0x19, 0x5, 0x1F, 0x8, 0x12, 0x1A, 0x1C, 0x0E, 0]
byte_40F0E0 = [0x67, 0x79, 0x7B, 0x7F, 0x75, 0x2B, 0x3C, 0x52, 0x53, 0x79, 0x57, 0x5E, 0x5D, 0x42, 0x7B, 0x2D, 0x2A, 0x66, 0x42, 0x7E, 0x4C, 0x57, 0x79, 0x41, 0x6B, 0x7E, 0x65, 0x3C, 0x5C, 0x45, 0x6F, 0x62, 0x4D]
str1 = [0] * 33
flag = ''
for i in range(33):
byte_40F0E0[i] ^= dword_40F040[i]
str1[dword_40F040[i]] = byte_40F0E0[i]
for i in range(33):
flag += chr(str1[i])
print(flag)
#flag{Tr4nsp0sltiON_Clph3r_1s_3z}