做点简单题提升信心用了...其实挺水的
一.csaw2013reversing2
查壳没有,是32位,ida进入查看
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{int v3; // ecxCHAR *lpMem; // [esp+8h] [ebp-Ch]HANDLE hHeap; // [esp+10h] [ebp-4h]hHeap = HeapCreate(0x40000u, 0, 0);lpMem = (CHAR *)HeapAlloc(hHeap, 8u, SourceSize + 1);memcpy_s(lpMem, SourceSize, &unk_409B10, SourceSize);if ( !sub_40102A() && !IsDebuggerPresent() ){MessageBoxA(0, lpMem + 1, "Flag", 2u);HeapFree(hHeap, 0, lpMem);HeapDestroy(hHeap);ExitProcess(0);}__debugbreak();sub_401000(v3 + 4, lpMem);ExitProcess(0xFFFFFFFF);
}
发现if ( !sub_40102A() && !IsDebuggerPresent() )可以看到前一个函数返回的是0,所以!0是永真,所以当动态调试的时候就不进入if语句,我们看到提示
听说运行就能拿到Flag,不过菜鸡运行的结果不知道为什么是乱码
我们运行输出一段数据
所以猜测有解密代码在程序中
我们看到下面的函数有和上面密文引用同一段数据,猜测是解密数据
让后修改汇编逻辑使程序跳过动态调试监测和进入解密函数
把一开始的&&换成||或者不管另一个条件
让后自己跟着流程看一遍汇编,发现解密函数sub_71000在函数loc_71096中
这两个是if判断条件
所以把
text:0007108A jnz short loc_71096
改成 jz short loc_71096
直接跳转就不用管后边的条件了
让后解密函数后面的loc_710EF是退出程序的函数,我们修改到输出数据的函数就行了
猜测是loc_710B9因为原文中if语句中有MessageBoxA
之后运行程序f8单步运行
之后出现了flag
flag{reversing_is_not_that_hard!}
二.maze
这是一道迷宫问题,进入主函数查看给相应的函数命名
__int64 __fastcall main(int a1, char **a2, char **a3)
{__int64 v3; // rbxint v4; // eaxbool v5; // bpbool v6; // alconst char *v7; // rdiint v9; // [rsp+0h] [rbp-28h] BYREFint v10[9]; // [rsp+4h] [rbp-24h] BYREFv10[0] = 0;v9 = 0;puts("Input flag:");scanf("%s", &s1);if ( strlen(&s1) != 24 || strncmp(&s1, "nctf{", 5uLL) || *(&byte_6010BF + 24) != '}' ){
LABEL_22:puts("Wrong flag!");exit(-1);}v3 = 5LL;if ( strlen(&s1) - 1 > 5 ){while ( 1 ){v4 = *(&s1 + v3);v5 = 0;if ( v4 > 'N' ){if ( v4 == 'O' ){v6 = lift(v10); // 左goto LABEL_14;}if ( v4 == 'o' ){v6 = right(v10); // 右goto LABEL_14;}}else{if ( v4 == '.' ){v6 = up(&v9); // 上goto LABEL_14;}if ( v4 == '0' ){v6 = down(&v9); // 下
LABEL_14:v5 = v6;}}if ( !index(map, v10[0], v9) )goto LABEL_22;if ( ++v3 >= strlen(&s1) - 1 ){if ( v5 )break;
LABEL_20:v7 = "Wrong flag!";goto LABEL_21;}}}if ( map[8 * v9 + v10[0]] != '#' )goto LABEL_20;v7 = "Congratulations!";
LABEL_21:puts(v7);return 0LL;
}
我们可以先看显示当前位置的函数index
__int64 __fastcall sub_400690(__int64 a1, int a2, int a3)
{__int64 result; // raxresult = *(a1 + a2 + 8LL * a3); // a2是左右移动,a3是上下移动,并且可以知道一层有8个数LOBYTE(result) = result == ' ' || result == '#';// 空格和#是道路return result;
}
让后查看地图,提取出来可以看出有64个位置,正好64/8=8,所以我们就可以知道大致规则了
有一个8*8的地图,其中. 0 O o 分别表示上 下 左 右
之后打印地图,写出步骤,我们还可以知道24位的flag除去格式nctf{}剩下了18位之后可以检验我们的答案
#include<stdio.h>
int main()
{char map[]=" ******* * **** * **** * *** *# *** *** *** *********";for(int i=0;i<64;i++){if(map[i]==' ')printf("0 ");if(map[i]=='*')printf("1 ");if(map[i]=='#')printf("# ");if((i%8)==7){printf("\n");}}
}
所以是
. 0 O o 分别表示上 下 左 右
nctf{o0oo00O000oooo..OO}
三.dmd-50
进入后查看发现有密文对比,之后上面发现有一个md5加密
其中,第一个数据转成字符让后记住大小段序,因为是ELf文件在windows的ida中打开的,所以要把转换后的'87'当成是78两个整数
#include<stdio.h>
int main()
{char a[]={48,52,51,56,100,53,98,54,101,50,57,100,98,48,56,57,56,98,99,52,102,48,50,50,53,57,51,53,99,48};puts(a);
}
//780438d5b6e29db0898bc4f0225935c0
//b781cbb29054db12f88f08c6e161c199
之后md5网站解决
b781cbb29054db12f88f08c6e161c199
四.srm-50
进入ida 32位查看
因为是exe可执行文件,所以打开文件运行一遍分析代码
INT_PTR __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{HMODULE ModuleHandleW; // eaxHICON IconW; // eaxHMODULE v7; // eaxHWND DlgItem; // eaxHCURSOR CursorW; // [esp-4h] [ebp-34Ch]CHAR String[256]; // [esp+8h] [ebp-340h] BYREFCHAR v11[256]; // [esp+108h] [ebp-240h] BYREFCHAR Text[256]; // [esp+208h] [ebp-140h] BYREFchar Source[36]; // [esp+308h] [ebp-40h] BYREFchar v14[24]; // [esp+32Ch] [ebp-1Ch] BYREFif ( a2 == 16 ){EndDialog(hDlg, 0);return 0;}if ( a2 == 272 ){ModuleHandleW = GetModuleHandleW(0);IconW = LoadIconW(ModuleHandleW, 0x67);SetClassLongA(hDlg, -14, IconW);v7 = GetModuleHandleW(0);CursorW = LoadCursorW(v7, 0x66);DlgItem = GetDlgItem(hDlg, 1);SetClassLongA(DlgItem, -12, CursorW);return 1;}if ( a2 != 273 || a3 != 1 )return 0;memset(String, a3 - 1, sizeof(String));memset(v11, 0, sizeof(v11));memset(Text, 0, sizeof(Text));GetDlgItemTextA(hDlg, 1001, String, 256);GetDlgItemTextA(hDlg, 1002, v11, 256);if ( strstr(String, "@") && strstr(String, ".") && strstr(String, ".")[1] && strstr(String, "@")[1] != 46 ){strcpy(v14, "Registration failure.");strcpy(Source, "Registration Success!\nYour flag is:");if ( strlen(v11) == 16&& v11[0] == 67&& v11[15] == 88&& v11[1] == 90&& v11[14] == 65&& v11[2] == 57&& v11[13] == 98&& v11[3] == 100&& v11[12] == 55&& v11[4] == 109&& v11[11] == 71&& v11[5] == 113&& v11[10] == 57&& v11[6] == 52&& v11[9] == 103&& v11[7] == 99&& v11[8] == 56 ){strcpy_s(Text, 0x100u, Source);strcat_s(Text, 0x100u, v11);}else{strcpy_s(Text, 0x100u, v14);}}else{strcpy_s(Text, 0x100u, "Your E-mail address in not valid.");}MessageBoxA(hDlg, Text, "Registeration", 0x40u);return 1;
}
发现有一个登录界面
我们应该是需要输入正确的邮箱和密码才可以,之后分析代码
可知string是邮箱,v11是密码,之后看要求
学习函数
`strstr` 是一个标准的 C 语言字符串处理函数,用于在一个字符串中查找另一个字符串(子字符串)的首次出现位置。它的语法如下:
```c
char* strstr(const char* haystack, const char* needle);
```### 参数说明:
1. **`haystack`**:主字符串(被搜索的字符串)。
2. **`needle`**:要查找的子字符串。### 返回值:
- 如果 `needle` 在 `haystack` 中存在,则返回指向 `haystack` 中首次出现 `needle` 的指针。
- 如果 `needle` 不存在于 `haystack` 中,或者 `needle` 是空字符串(`""`),则返回 `NULL`。
所以我们可以知道string需要有 @ 有 '.' 而且@之后不能是 '.',并且 '.'之后有字符,这是检验邮箱的格式的,其他的在这里没有要求,让后密码可以在下面的if语句中看出来,随便写一个邮箱
得到flag就是密码CZ9dmq4c8g9G7bAX
五.Mysterious
exe文件运行之后看代码
int __stdcall DialogFunc_0(HWND hWnd, int a2, int a3, int a4)
{int v4; // eaxchar Source[260]; // [esp+50h] [ebp-310h] BYREF_BYTE Text[257]; // [esp+154h] [ebp-20Ch] BYREF__int16 v8; // [esp+255h] [ebp-10Bh]char v9; // [esp+257h] [ebp-109h]int Value; // [esp+258h] [ebp-108h]CHAR String[260]; // [esp+25Ch] [ebp-104h] BYREFmemset(String, 0, sizeof(String));Value = 0;if ( a2 == 16 ){DestroyWindow(hWnd);PostQuitMessage(0);}else if ( a2 == 273 ){if ( a3 == 1000 ){GetDlgItemTextA(hWnd, 1002, String, 260);strlen(String);if ( strlen(String) > 6 )ExitProcess(0);v4 = atoi(String);Value = v4 + 1;if ( v4 == 122 && String[3] == 'x' && String[5] == 'z' && String[4] == 'y' ){strcpy(Text, "flag");memset(&Text[5], 0, 252u);v8 = 0;v9 = 0;_itoa(Value, Source, 10);strcat(Text, "{");strcat(Text, Source);strcat(Text, "_");strcat(Text, "Buff3r_0v3rf|0w");strcat(Text, "}");MessageBoxA(0, Text, "well done", 0);}SetTimer(hWnd, 1u, 0x3E8u, TimerFunc);}if ( a3 == 1001 )KillTimer(hWnd, 1u);}return 0;
}
输入string长度不超过6,之后判断string,其中有这样一个函数
v4 = atoi(String);
实际上是ascll to int 字符型转换成整数,所以如果是122xyz的话会吧前面的122字符串转换成整数122让后赋值给v4
所以key是122xyz,如果是的话就输出flag,
得到flag
六.answer_to_everything
查壳是ELF64位文件,虽然是.exe后缀
之后简单分析得到了字符串#kdudpeh
-
Submit without any tags:提交时不要带任何标签
提交不对,让后提示中有sha1,之后sha1网站解决让后按照格式输入
flag{80ee2a3fe31da904c596d993f7f1de4827c1450a}
七.re1-100
进去有对flag格式的验证
看到有一个 confuseKey函数混淆关键,进去看看
__int64 __fastcall confuseKey(char *a1, int a2)
{char dest[8]; // [rsp+10h] [rbp-50h] BYREFint v4; // [rsp+18h] [rbp-48h]__int16 v5; // [rsp+1Ch] [rbp-44h]char v6; // [rsp+1Eh] [rbp-42h]char v7[8]; // [rsp+20h] [rbp-40h] BYREFint v8; // [rsp+28h] [rbp-38h]__int16 v9; // [rsp+2Ch] [rbp-34h]char v10; // [rsp+2Eh] [rbp-32h]char src[8]; // [rsp+30h] [rbp-30h] BYREFint v12; // [rsp+38h] [rbp-28h]__int16 v13; // [rsp+3Ch] [rbp-24h]char v14; // [rsp+3Eh] [rbp-22h]char v15[8]; // [rsp+40h] [rbp-20h] BYREFint v16; // [rsp+48h] [rbp-18h]__int16 v17; // [rsp+4Ch] [rbp-14h]char v18; // [rsp+4Eh] [rbp-12h]unsigned __int64 v19; // [rsp+58h] [rbp-8h]v19 = __readfsqword(0x28u);*dest = 0LL;v4 = 0;v5 = 0;v6 = 0;*v7 = 0LL;v8 = 0;v9 = 0;v10 = 0;*src = 0LL;v12 = 0;v13 = 0;v14 = 0;*v15 = 0LL;v16 = 0;v17 = 0;v18 = 0;if ( a2 != 42 )return 0LL;if ( !a1 )return 0LL;if ( strlen(a1) != 42 )return 0LL;if ( *a1 != 123 )return 0LL;strncpy(dest, a1 + 1, 10uLL);strncpy(v7, a1 + 11, 10uLL);strncpy(src, a1 + 21, 10uLL);strncpy(v15, a1 + 31, 10uLL);memset(a1, 0, 0x2AuLL);*a1 = 123;strcat(a1, src);strcat(a1, v15);strcat(a1, dest);strcat(a1, v7);a1[41] = 125;return 1LL;
}
其中有换位置的一部分
把第一段和第三段交换位置,把第二段和第四段交换位置,所以
{daf29f59034938ae4efd53fc275d81053ed5be8c}实际上是
{53fc275d81053ed5be8cdaf29f59034938ae4efd}
之后发现提交的时候是不需要花括号的
53fc275d81053ed5be8cdaf29f59034938ae4efd