BUUCTF
1. easyre[*]exeinfo查壳
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611102826820-1050503251.png
64位,无壳,用ida64打开
[*]首先查看字符串表
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611103120893-1866007985.png
发现flag
2.reverse1
[*]exeinfo查壳
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611103335482-1462425242.png
64位,无壳,用ida64打开
[*]首先查看字符串
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611103549695-536995825.png
发现疑似flag的字符串
[*]查看引用该字符串的函数
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611103806605-438304891.png
Str2即是该字符串。注意到有一个strcmp()函数,所以基本确定Str2即是flag。有一个for循环处理了Str2:当Str2中有一个字符的ASCII码等于111(o)时,替换为48(0)
所以flag为flag
注意:ida是静态调试器,内存中的数据是还没有经过各种代码处理的。例如本题的Str2,只有头几次出现(未被处理)时为hello_world,后面经过处理后就不是hello_world了,虽然在ida中仍然指向hello_world,这是因为Str2是一个指针,指向了保存hello_world的那块内存,在程序没有执行之前那块内存的内容不会改变!
3.reverse2
[*]注意到下载的文件并不是exe可执行文件!
查不了壳,不过仍然用exeinfo打开看看是32位的还是64位的
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611105705106-1357799553.png
64位,用ida64打开
[*]查看字符串表
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611105844135-1483917675.png
发现疑似flag的字符串,但是ctrl+x发现没有引用
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611111527453-660635271.png
但是,这里有一个非常值得注意的点,字符串名是一个指向字符串首位地址的指针,该地址往后的地址也是字符串的一部分,那么字符串在哪里截止呢?C/C++中/0即表示字符串停止,汇编中用
"*** ,0 ***"表示字符串结束。所以在这里变量flag指向了601081处,而601081处存储了78h(“{”),那么flag就是“{”了吗?当然不是,flag指向的字符串并没有这里截止,所以往后的aHackingForFun指向的字符串仍是flag的一部分,直到“,0”为止(db 0(空,nop)、ends(段结束) 也是字符串结尾的标志)
[*]跳转到引用flag变量的函数,F5反编译
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611150938315-1558141117.png
注意到line 27处有一个strcmp()函数,因此经过处理后的flag即是答案
[*]处理脚本(照抄即可):
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611153312921-1181094032.png
4.内涵的软件
[*]exeinfo查壳
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611153919512-890416607.png
32位,无壳,ida32打开
[*]查看字符串
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611154128414-1736716029.png
疑似flag,查看引用
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611154431736-837214856.png
进入引用函数,发现并没有处理此字符串,应该这个字符串就是答案(改为题述格式)
5.新年快乐
[*]exeinfo查壳
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611154851335-717164853.png
32位,用了UPX加壳
[*]脱壳
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611155142204-449382092.png
ida32打开
[*]查看字符串表
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611155537553-1800802335.png
看不出什么
[*]查看带有“flag”的提示字符串,进入引用函数,F5反编译转为C语言
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611155819556-357247949.png
注意line 12、13、14、15,说明v5是flag,没有经过程序处理,所以v4即是答案。
6.xor
[*]不是exe文件!
仍用exeinfo打开
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611160834273-1239224921.png
64位,用ida64打开
[*]查看字符串
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611160933672-845595616.png
发现很奇怪的一串东西,看看引用
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611161135732-943366634.png
没有函数引用它,只有一个变量_global指向了它
[*]再查看带有“flag”的提示字符串,进入引用函数,F5反编译转为C语言
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611161406465-1411494883.png
注意line 11、12、18、19,所以v6即是flag。v6经过一系列异或运算等于_global,所以对_global进行逆运算即可获取答案
[*]脚本程序:
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611162129350-465060494.png
注意:a ^ b = c,则 a ^ c = b , b ^ c = a
7.helloword
[*]注意是一个apk文件,所以要用apk反编译软件,反编译后打开字符串表搜索flag即可获取答案
变种的第1题
8.reverse3
[*]查壳
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611165844883-933419393.png
32位,无壳,用ida32打开
[*]查看字符串表
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611170015607-39861993.png
注意到“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=”,所以可以确认是进行了base64加密
[*]查看带有“flag”的提示字符串,进入引用函数,F5反编译转为C语言
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611170510645-1298008261.png
可以看出,Str即是flag,接下来就是还原Str了,即对Str2进行逆向处理
[*]跟踪line 24的sub_4110BE函数
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611170911783-2039267694.png
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611171012104-304552166.png
这个函数即是base64加密函数
[*]处理脚本:
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611171239459-788179086.png
9.不一样的flag
[*]查壳
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611171352275-1026729988.png
32位,无壳,用ida32打开
[*]查看字符串表
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611171613266-2033399639.png
初步判断应该是一个小游戏,通过不断选择上下左右而获取flag
[*]进入引用函数
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611172015909-907283007.png
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611172045455-191501213.png
line 51、53中的49、35分别对应1、#
所以应该是一个迷宫程序,将*11110100001010000101111#分成五排五列,不经过1到达#所执行的按键组合即是答案
10.SimpleRev
[*]不是exe文件。
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611200759308-1125219195.png
64位,用ida64打开
[*]查看字符串
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611200927958-920171327.png
看不出什么。
[*]进入提示字符串引用函数
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611201433168-357143926.png
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611201521668-196281044.png
[*]分析程序流程
[*]给src(将十进制转为十六进制(0x534C43444E),一个字节一个字节对照ASCII码表(ida快捷键“R”)就可以得到对应字符串为“SLCDN”(不能直接用十进制下的数据两两对照,计算机处理的是16进制!经过十进制化的数据必须要还原成16进制才能对照ASCII码表,除非只是一个字节的数据!),但是,只要是英特尔或AMD的x86/x64架构那么一定是小端序,所以该十六进制数实际处理时是0x4E44434C53,因此程序实际处理的字符串为“NDCLS”)和v9(同理可得程序实际处理的值为“hadow”)赋值
[*]调用join()函数,参数为key3(存储的值为“kills”,字符串名本身是指针)和v9的指针
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611202514476-2125250719.png
可以看出,join()函数的作用是将key3和v9拼接起来,并赋给text("killshadow")(malloc()分配内存,返回指向此内存的指针)
3. line 24、25将key1(值为“ADSFK”)和src拼接赋给key(“ADSFKNDCLS”)
4. 处理key,得到v3和新的key
5. 由line 36、39可以得知v1是flag。通过逐个处理v1的字符修改str2,最后str2的值要与text("killshadow")相等
[*]处理脚本:
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611215056132-674015910.png
11.Java逆向解密
[*]使用jd-gui反编译
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220611231904026-623676676.png
这段程序的意思是:输入的字符串依次+‘@’,然后跟32异或,得到KEY数组里的值
所以只要反过来即可:将KEY数组中的值逐个与32异或,再-‘@’
12.luck_guy
[*]exeinfo打开
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220612083237919-1281738363.png
64位,ida64打开
[*]查看字符串表
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220612090832746-1474632768.png
形似flag
[*]进入引用函数(也可以从main()函数一步步分析过来)
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220612090940325-97642422.png
[*]分析函数流程
1.v0接收当前时间戳,以v0为种子,以此产生4个(伪)随机数,对200求余后分别运行子程序
2.由case 1可知s即为flag,它由f1(GXY{do_not_)和f2拼接而成,而f2由case 4得到并经case 5处理,所以应该按照5——>4——>1的流程即可获取真正的flag
注意:line 33中给s赋的值是小端序,得到的字符串要逆转过来(“icug`of ”)
[*]处理脚本:
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220612091825731-553673927.png
13.刮开有奖
[*]查壳
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220613084609949-36517061.png
32位,无壳,用ida32打开
[*]查看字符串表
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220613084743235-116901363.png
base64加密
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220613084850720-1338070775.png
这种奇奇怪怪的字符串多半跟flag有关
[*]分析程序的函数执行流程
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220613085105277-1283368013.png
搜索main,发现有个WinMain()函数(主函数),调用了DialogBoxParam()来显示对话框,参数里有个DialogFunc,这是对话框过程函数,用来给对话框处理用户或系统的行为,这应该就是目标了
[*]查看DialogFunc()
BOOL __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
const char *v4; // esi
const char *v5; // edi
int v7; //
int v8; //
int v9; //
int v10; //
int v11; //
int v12; //
int v13; //
int v14; //
int v15; //
int v16; //
int v17; //
CHAR String; //
char v19; //
char v20; //
char v21; //
char v22; //
char v23; //
char v24; //
char v25; //
char v26; //
char v27; //
char v28; //
if ( a2 == 272 )
return 1;
if ( a2 != 273 )
return 0;
if ( (_WORD)a3 == 1001 )
{
memset(&String, 0, 0xFFFFu);
GetDlgItemTextA(hDlg, 1000, &String, 0xFFFF);
if ( strlen(&String) == 8 )
{
v7 = 90;
v8 = 74;
v9 = 83;
v10 = 69;
v11 = 67;
v12 = 97;
v13 = 78;
v14 = 72;
v15 = 51;
v16 = 110;
v17 = 103;
sub_4010F0(&v7, 0, 10);
memset(&v26, 0, 0xFFFFu);
v26 = v23;
v28 = v25;
v27 = v24;
v4 = (const char *)sub_401000(&v26, strlen(&v26));
memset(&v26, 0, 0xFFFFu);
v27 = v21;
v26 = v20;
v28 = v22;
v5 = (const char *)sub_401000(&v26, strlen(&v26));
if ( String == v7 + 34
&& v19 == v11
&& 4 * v20 - 141 == 3 * v9
&& v21 / 4 == 2 * (v14 / 9)
&& !strcmp(v4, "ak1w")
&& !strcmp(v5, "V1Ax") )
{
MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
}
}
return 0;
}
if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 )
return 0;
EndDialog(hDlg, (unsigned __int16)a3);
return 1;
}这里注意到有两处连续的变量声明,同时地址也很连续,且使用的时候也比较连续,非常有可能是数组,因此ida-edit-Array对这两处一连串变量创建数组
注意:一定要确定好数组的起始地址和结束地址,可以通过双击ida反汇编伪代码的数组起始/结束变量跳转到相应地址,以此确定数组范围
[*]创建数组后的DialogFunc()
BOOL __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
const char *v4; // esi
const char *v5; // edi
int v7; //
char String; //
char v9; //
if ( a2 == 272 )
return 1;
if ( a2 != 273 )
return 0;
if ( (_WORD)a3 == 1001 )
{
memset(String, 0, 0xFFFFu);
GetDlgItemTextA(hDlg, 1000, String, 0xFFFF);
if ( strlen(String) == 8 )
{
v7 = 90;
v7 = 74;
v7 = 83;
v7 = 69;
v7 = 67;
v7 = 97;
v7 = 78;
v7 = 72;
v7 = 51;
v7 = 110;
v7 = 103;
sub_4010F0(v7, 0, 10);//处理v7数组(实际上是排序)
memset(v9, 0, 0xFFFFu);
v9 = String;
v9 = String;
v9 = String;
v4 = sub_401000((int)v9, strlen(v9));//base64加密
memset(v9, 0, 0xFFFFu);
v9 = String;
v9 = String;
v9 = String;
v5 = sub_401000((int)v9, strlen(v9));//base64加密
if ( String == v7 + 34
&& String == v7
&& 4 * String - 141 == 3 * v7
&& String / 4 == 2 * (v7 / 9)
&& !strcmp(v4, "ak1w")
&& !strcmp(v5, "V1Ax") )
{
MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
}
}
return 0;
}
if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 )
return 0;
EndDialog(hDlg, (unsigned __int16)a3);
return 1;
}较比创建数组前,代码的可读性强了很多
注意到GetDlgItemTextA()函数,这个函数的用处是复制对话框中的字符串到lpString参数(第3个参数)指向的缓冲区,即保存输入到指定变量。再加上后面一系列的对String的比较因此String很有可能就是flag
[*]逐个分析关键函数(sub_4010F0、sub_401000)
[*]sub_4010F0
这个函数实在是太复杂了,因此直接照抄(注意加上头文件,以及删掉例如(_DWORD *)的汇编表示(取4个字节),然后将各种基址+偏移的表示也换成数组的寻址),跑一下程序看看结果
[*]sub_401000
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220613095128553-1389864466.png
发现有个byte_407830数组,双击查看
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220613095323699-1383775520.png
(41h即“A”)
所以可以确定这是个base64加密函数,而且看一下参数,发现两次都是对v9数组的处理,只是两次对v9数组赋的值不同
接下来只要这个确认String数组中的每一个字符即可获取答案
14.
22.SignIn
[*]例行exeinfo检查
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220613151315281-1715677007.png
64位,用ida64打开
[*]查看字符串表
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220613152023421-487935021.png
程序调用了__gmpz_init_set_str函数,这是一个GNU高精度算法库,在RSA加密中较为常见,在加上65537这个十分敏感的数据,就可以确定这是一道关于RSA加密的题
rsa加密详解:https://blog.csdn.net/dbs1215/article/details/48953589
[*]查看主函数
https://img2022.cnblogs.com/blog/2902545/202206/2902545-20220613152232643-1844322801.png
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页:
[1]