Revers-上半场:
Re1:
查壳:64位无壳
托ida里分析一下
主算法:p1[i] = i + flag[i];
写脚本逆一下 C++脚本:
void re1()
{
char cp[32];
cp[0] = 110;
cp[1] = 122;
cp[2] = 112;
cp[3] = 120;
cp[4] = 103;
cp[5] = 121;
cp[6] = 108;
cp[7] = 130;
cp[8] = 112;
cp[9] = 110;
cp[10] = 59;
cp[11] = 60;
cp[12] = 123;
cp[13] = 108;
cp[14] = 130;
cp[15] = 119;
cp[16] = 68;
cp[17] = 112;
cp[18] = 100;
cp[19] = 120;
cp[20] = 138;
cp[21] = 122;
cp[22] = 136;
cp[23] = 138;
cp[24] = 125;
cp[25] = 120;
cp[26] = 145;
cp[27] = 138;
cp[28] = 142;
cp[29] = 137;
cp[30] = 130;
cp[31] = 156;
for (int i = 0; i < 32; i++)
{
cout << (char)(cp[i] - i);
}
}
得到flag:ynuctf{he11o_th4_Reverse_world}
Re2:
查壳:32位无壳
分析代码:
可以看到有三个加密:
encode1先对base64原码表进行反转(一直没看到卡在这里卡了好久)后对字符串进行base64加密
Encode2
一:符串进行异或操作 二位运算左移8位
三:位置1 四:除256
Encode3只是简单的字符串比较
在encode3中发现被加密的字符串
C++脚本解encode2:
void re2(){
char flag[60];
int str[] = { 0x6A,0x5B,0x62,0x56,0x6C,0x76,0x7E,0x44,0x64,0x53,0x5F,0x47,0x74,0x44,0x7D,0x40,0x7F,0x58,0x20,0x58,0x78,0x2F,0x5C,0x79,0x77,0x6A,0x69,0x57,0x2D,0x6D,0x69,0x68,0x4C,0x52,0x59,0x77,0x5D,0x1E,0x8,0x6F,0x53,0x5E,0x67,0x63,0x54,0x16,0x4E,0x52,0x5F,0x7F,0x1,0x50,0x4F,0x7B,0x18,0x7F,0x54,0x49,0x10,0x7F };
int i,len=60;
int ret[60];
for (int a = 0; a < 60; a++) {
for (int i = 0;; i++) {
ret[a] = (a + 1) ^ i;
ret[a] <<= 8;
ret[a] |= 0x7Fu;
ret[a] /= 256;
if (str[a] == ret[a]) {
cout << (char)i; break;
}
}
}
}
得到字符串:kYaRipyLmYTKyJrPnJ3Lm9KanprK0svHmpzSx8/GztLOy8abnM2dzM/Gms+C
Void base(){
char base[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char str[] = "/+9876543210zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA";
char key[] = "kYaRipyLmYTKyJrPnJ3Lm9KanprK0svHmpzSx8/GztLOy8abnM2dzM/Gms+C";
for (int i = 0; i < sizeof(key) - 1; i++){
for (int j = 0; j < sizeof(str) - 1; j++){
if (key[i] == str[j])
cout << base[j];
}
}
}
根据原码表转化为正常base64:
bnludWN0Zns1N2UwY2I0ZC1lYWU1LTQ4ZWMtODA5MS0xNDlkYzJiMzA5ZTB9
网站解base64得到flag:nynuctf{57e0cb4d-eae5-48ec-8091-149dc2b309e0}
Re3:
查壳:32位无壳
运行发现是一个小游戏
在游戏中有凯撒魔王和各种对9这个数字的提示
判断有凯撒加密密钥为9的字符串
在ida的story_4中发现flag1字符串以及凯撒加解密操作
Flag1: epelZk]rZXj\i
Story_5中发现flag2的赋值操作
可恶的迷宫 ( o`ω′)ノ(手撸)
得到:ssddwddssssdsssddwwwwwwd
Story_6中进行异或操作
写出脚本解密两段flag拼在一起
void re3()
{
char str1[] = "epelZk]rZXj\\i";
for (int i = 0; i < 13; i++)
{
str1[i] += 9;
cout << str1[i];
}
char key[] = "ssddwddssssdsssddwwwwwwd";
char str2[] = { 44,30,5,30,18,59,5,29,23,44,11,11,1,44,26,23,59,18,22,4,14,86,86,25,0,0 };
for (int i = 0; i < 24; i++)
{
key[i] ^= str2[i];
cout << key[i];
}
}
Flag: nynuctf{caser_maze_and_xor_is_easy!!}
Revers-下半场:
Re1:
查壳:无壳32位
拖进ida静态调试:
找到加密和对比函数
在对比函数参数位置找到密文字符串:
6E796E756374667B48656C6C6F5F546869735F49735F415F53696D706C655F4865782121217D
发现只需要解ascii
解得flag: nynuctf{Hello_This_Is_A_Simple_Hex!!!}
Easy_game:
解压得到扫雷游戏,通过即可获得flag
我试了一下用dbg破解过了二十多关仍未出现flag
根据提示打开1文件发现是游戏源代码
找到关键代码段
分析代码 依次按vir数组键入会使vir数组和vir2素组异或操作
键入等于27时写入secret
写出脚本
void re2xia()
{
int vir[12] = { 38,40,37,39,66,65,0 };
int vir2[92] = { 72, 96, 96, 107, 46, 86, 96, 122, 80, 103, 110, 121, 106, 80, 124,
122, 108, 108, 106, 124, 124, 105, 122, 99, 99, 118, 80, 108, 96, 98, 127, 99, 106,
123, 106, 107, 80, 123, 103, 106, 80, 104, 110, 98, 106, 46, 65, 96, 120, 80, 104,
102, 121, 106, 80, 118, 96, 122, 80, 105, 99, 110, 104, 53, 97, 118, 97, 122, 108,
123, 105, 116, 95, 62, 59, 118, 80, 104, 59, 98, 106, 58, 80, 103, 59, 127, 127, 102,
99, 118, 114,0 };
int vir3[100] = { 107, 46, 86, 96, 122, 80, 103, 110, 121, 106, 80, 124,
122, 108, 108, 106, 124, 124, 105, 122, 99, 99, 118, 80, 108, 96, 98, 127, 99, 106,
123, 106, 107, 80, 123, 103, 106, 80, 104, 6, 96, 107, 46, 86, 96, 122, 80, 103, 110, 121, 106, 80, 124,
122, 108, 108, 106, 124, 1 };
for (int i = 0; i < 7; i++)
{
for (int j = 0; j < 91; j++)
{
vir2[j] ^= vir[i];
}
}
for (int i = 0; i < 91; i++)
cout << (char)vir2[i];
}
得到flag: nynuctf{P14y_g4me5_h4ppily}
Baby_code:
拖到ida静态分析
给出了密文res数组
主要加密与之前遇到过的一个rot类似,后面还有个数组每个数-48操作和字符串反转
同时发现res数组缺失res[34]看过算法后决定先解一下试试
第一个算法可以得到res应该是0到9可以最后爆破
写出解题脚本:
void re3xia()
{
char res[50];
res[0] = 3; res[1] = 9; res[2] = 9; res[3] = 8; res[4] = 3; res[5] = 8;
res[6] = 4; res[7] = 3; res[8] = 9; res[9] = 6; res[10] = 3; res[11] = 6;
res[12] = 3; res[13] = 8; res[14] = 1; res[15] = 3; res[16] = 3; res[17] = 6;
res[18] = 9; res[19] = 6; res[20] = 5; res[21] = 3; res[22] = 2; res[23] = 8;
res[24] = 9; res[25] = 6; res[26] = 6; res[27] = 8; res[28] = 9; res[29] = 6;
res[30] = 4; res[31] = 1; res[32] = 1; res[33] = 9; res[35] = 7; res[36] = 4;
res[37] = 8; res[38] = 7; res[39] = 6; res[40] = 5; res[41] = 8; res[42] = 8;
res[43] = 7; res[44] = 9; res[45] = 8; res[46] = 8; res[47] = 7;
int temp;
res[34] = 0; //试出来的
for (int i_1 = 0; i_1 <= 23; ++i_1)
{
temp = res[i_1];
res[i_1] = res[47 - i_1];
res[47 - i_1] = temp;
}
char cp[50];
for (int i_0 = 0; i_0 <= 47; ++i_0)
{
res[i_0] = res[i_0] + 48;
cp[i_0] = res[i_0];
}
char flag[50];
for (int i = 0; i < 48; i++)
{
for (int j = 0; j < 128; ++j)
{
int n = j - 32;
int o = j + 32;
int l = j - 18;
if (cp[2 * i] == n / 10 % 10 + 48 && cp[2 * i + 1] == n % 10 + 48 && j > 91 && j != 127)
{
flag[i]= (char)j;
continue;
}
else if (cp[2 * i] == o / 10 % 10 + 48 && cp[2 * i + 1] == o % 10 + 48 && j > 64 && j <= 90)
{
flag[i] = (char)j;
continue;
}
else if (cp[2 * i] == l / 10 % 10 + 48 && cp[2 * i + 1] == l % 10 + 48)
{
flag[i] = (char)j;
}
}
}
cout << flag;
cout << endl;
}
先将字符串倒置,再减去48,最后进行暴力破解
主要算法将输入的数n满足一定条件加减一个数后除10再取余10加48放入res[2i]
将n满足一定条件加减一个数后取余10加48放入res[2i+1]
通过遍历0-128找到一个数使他能满足以上条件这个数就是要找的字符
(res[34]是我后来试出来的,没这个数左大括号会乱码但是并不影响解出来的flag)
运行得到flag: nynuctf{Rever5e_1s_e4sy}