打开题目,下载附件,拖入pe中查看有无壳
无壳
拖入ida中
shift+f12找到可疑的字符串,跟进查看
找到如下代码,分析可知,当dword_4099F0的值达到19999时,会输出BJD{%d%d2069a45792d233ac}对应的字符串,其中%d%d会被替换成199990
sprintf的具体用法参考如下https://www.baidu.com/baidu?tn=monline_4_dg&ie=utf-8&wd=sprintf%E5%87%BD%E6%95%B0%E7%9A%84%E7%94%A8%E6%B3%95
所以得到flag 为flag{1999902069a45792d233ac}
学到的知识点:sprintf函数的含义
buu题解——luck_guy
打开题目,下载附件,解压缩
拖入PE中,发现无壳
拖入ida中
shift+F12查看字符串,找到可疑字符串
分别跟进,找到如下代码
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [rsp+14h] [rbp-Ch] BYREF
unsigned __int64 v5; // [rsp+18h] [rbp-8h]
v5 = __readfsqword(0x28u);
welcome(argc, argv, envp);
puts("_________________");
puts("try to patch me and find flag");
v4 = 0;
puts("please input a lucky number");
__isoc99_scanf("%d", &v4);
patch_me(v4);
puts("OK,see you again");
return 0;
}
此为主函数,进入patch_me即为如下函数
unsigned __int64 get_flag()
{
unsigned int v0; // eax
int i; // [rsp+4h] [rbp-3Ch]
int j; // [rsp+8h] [rbp-38h]
__int64 s; // [rsp+10h] [rbp-30h] BYREF
char v5; // [rsp+18h] [rbp-28h]
unsigned __int64 v6; // [rsp+38h] [rbp-8h]
v6 = __readfsqword(0x28u);
v0 = time(0LL);
srand(v0);
for ( i = 0; i <= 4; ++i )
{
switch ( rand() % 200 )
{
case 1:
puts("OK, it's flag:");
memset(&s, 0, 0x28uLL); // 将s字符串数组全部初始化为0
strcat(&s, f1);
strcat(&s, &f2);
printf("%s", &s);
break;
case 2:
printf("Solar not like you");
break;
case 3:
printf("Solar want a girlfriend");
break;
case 4:
s = 0x7F666F6067756369LL;
v5 = 0;
strcat(&f2, &s);
break;
case 5:
for ( j = 0; j <= 7; ++j )
{
if ( j % 2 == 1 )
*(&f2 + j) -= 2;
else
--*(&f2 + j);
}
break;
default:
puts("emmm,you can't find flag 23333");
break;
}
}
return __readfsqword(0x28u) ^ v6;
}
对如上函数分析,主函数输入的v4字符串经过patch_me处理后得到flag
对patch_me函数分析
代码中meset函数含义参考:https://baike.baidu.com/item/memset/4747579
随机获取一个数,然后经过switch语句,可以看出flag 是s字符数组,而s由f1,f2组成。
跟进f1得到
由代码知得到f2的过程为case 4->5->1
写脚本得到flag
#include<stdio.h>
int main(){
int j;
char f1[]="GXY{do_not_";
char f2[9]="icug`of";
f2[7]=0x7F;
for ( j = 0; j <= 7; ++j )
{
if ( j % 2 == 1 )
*(f2 + j) -= 2;
else
--*(f2 + j);
}printf("%s",f1);
for(j=0;j<=7;j++){
printf("%c",f2[j]);
}
return 0;
}
学到的知识点:1.s在内存中的存储为小端存储,即s的字符串顺序应反过来
2.对于s字符串中的\符号不能直接写在字符串数组内部(不然会报错哦)而应该单独拿出来处理
3.meset函数含义(作用是将某一块内存中的内容全部设置为指定的值,通常初始化使用)
buu题解——rome
打开题目,下载附件,解压拖入PE中查看有壳无壳
无壳,且为32位,拖入ida中查看
主函数没发现什么,shift+f12找可疑的字符串,猜测flag就在贯标所在的字符串内,跟进
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 == 'A' )
{
result = v3;
if ( v3 == 'C' )
{
result = v4;
if ( v4 == 'T' )
{
result = v5;
if ( v5 == 'F' )
{
result = v6;
if ( v6 == '{' )
{
result = v11;
if ( v11 == '}' )
{
v1[0] = v7;
v1[1] = v8;
v1[2] = v9;
v1[3] = v10;
*&v12[17] = 0;
while ( *&v12[17] <= 15 )
{
if ( *(v1 + *&v12[17]) > 64 && *(v1 + *&v12[17]) <= 90 )
*(v1 + *&v12[17]) = (*(v1 + *&v12[17]) - 51) % 26 + 65;
if ( *(v1 + *&v12[17]) > 96 && *(v1 + *&v12[17]) <= 122 )
*(v1 + *&v12[17]) = (*(v1 + *&v12[17]) - 79) % 26 + 97;
++*&v12[17];
}
*&v12[17] = 0;
while ( *&v12[17] <= 15 )
{
result = v12[*&v12[17]];
if ( *(v1 + *&v12[17]) != result )
return result;
++*&v12[17];
}
return printf("You are correct!");
}
}
}
}
}
}
return result;
}
找到如上代码,中间的两个while 循环是加密运算,
当加密后 的值与v12相等时得到flag(即什么ascll码值经过加密运算后与v12相等,我们要找到就是这个ascll码值)
写脚本代码
#include<stdio.h>
int main(){
char v12[29]="Qsw3sj_lz4_Ujw@l";
int k,i,z;
char flag[]={0};
printf("ACTF{");
for(k=0;k<16;k++){
for(i=0;i<127;i++){
z=i;
if ( i> 64 &&i <= 90 )
i = (i- 51) % 26 + 65;
if ( i> 96 && i <= 122 )
i= (i - 79) % 26 + 97;
if(i==v12[k])
flag[k]=z;
}printf("%c",flag[k]);
}
printf("}");
return 0;
}
得到flag
flag{Cae3ar_th4_Gre@t}
学到的知识点:通过遍历所有ascll码值,判断经过加密后的值是否与要比较的值相等来找flag
称为暴力破解(后来发现此加密过程时凯撒+大小写转换)