https://adworld.xctf.org.cn/task/task_list?type=reverse&number=4&grade=0
https://adworld.xctf.org.cn/task/task_list?type=reverse&number=4&grade=1

新手练习区

open-source(c)

难度系数: 3.0 题目来源: HackYou CTF 题目描述:菜鸡学逆向学得头皮发麻,终于它拿到了一段源代码 题目场景: 暂无 题目附件: 附件1.c

附件1.c

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main(int argc, char *argv[]) {
  4. if (argc != 4) {
  5. printf("what?\n");
  6. exit(1);
  7. }
  8. unsigned int first = atoi(argv[1]);
  9. if (first != 0xcafe) {
  10. printf("you are wrong, sorry.\n");
  11. exit(2);
  12. }
  13. unsigned int second = atoi(argv[2]);
  14. if (second % 5 == 3 || second % 17 != 8) {
  15. printf("ha, you won't get it!\n");
  16. exit(3);
  17. }
  18. if (strcmp("h4cky0u", argv[3])) {
  19. printf("so close, dude!\n");
  20. exit(4);
  21. }
  22. printf("Brr wrrr grr\n");
  23. unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207;
  24. printf("Get your key: ");
  25. printf("%x\n", hash);
  26. return 0;
  27. }
  • 可以看出 29 行在计算 key,需要用到 first、second、argv3
  • 5-8 行:必须满足输入 4 个参数(exe文件本身是 argv0)即:1.exe(argv0) argv1 argv2 argv3
  • 10-14 行:atoi 是将 ASCII串 转为 int, first 必须为 0xcafe
  • 16-20 行:second 除 5 不能余 3,除 17 要余 8,用 python 计算:

    1. for i in range(1000):
    2. if i % 5 != 3 and i % 17 == 8:
    3. print(i)

    得到:25, 42, 59, 76, …… 取 second = 25

  • 22-25 行:argv3 必须为 “h4cky0u”

  • 修改程序计算 key
    1. unsigned int hash = 0xcafe * 31337 + (25 % 17) * 11 + strlen("h4cky0u") - 1615810207;
    程序输出:Get your key: c0ffee

insanity(elf)

难度系数: 3.0 题目来源: 9447 CTF 2014 题目描述:菜鸡觉得前面的题目太难了,来个简单的缓一下 题目场景: 暂无 题目附件: 附件1

附件给出一个没有后缀名的文件,拖到 010Editor,可以看出这是一个 ELF 文件
搜索 flag,发现 9447{This_is_a_flag}

python-trade(pyc)

难度系数: 3.0 题目来源: NJUPT CTF 2017 题目描述:菜鸡和菜猫进行了一场Py交易 题目场景: 暂无 题目附件: 附件1.pyc

放到 https://tool.lu/pyc 上反编译

  1. import base64
  2. def encode(message):
  3. s = ''
  4. for i in message:
  5. x = ord(i) ^ 32
  6. x = x + 16
  7. s += chr(x)
  8. return base64.b64encode(s)
  9. correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt'
  10. flag = ''
  11. print 'Input flag:'
  12. flag = raw_input()
  13. if encode(flag) == correct:
  14. print 'correct'
  15. else:
  16. print 'wrong'

分析代码,编写程序解 flag

  1. import base64
  2. s = base64.b64decode('XlNkVmtUI1MgXWBZXCFeKY+AaXNt')
  3. flag = ''
  4. for i in s:
  5. x = (i - 16) ^ 32
  6. flag += chr(x)
  7. print(flag)

flag: nctf{d3c0mpil1n9_PyC}

re1(exe)

难度系数: 4.0 题目来源: DUTCTF 题目描述:菜鸡开始学习逆向工程,首先是最简单的题目 题目场景: 暂无 题目附件: 附件1.exe

拖到 010Editor,搜索 flag,得到 DUTCTF{We1c0met0DUTCTF}

game(exe)

难度系数: 4.0 题目来源: ZSCTF 题目描述:菜鸡最近迷上了玩游戏,但它总是赢不了,你可以帮他获胜吗 题目场景: 暂无 题目附件: 附件1.exe

IDA 打开,查看伪代码 main -> main_0 -> sub_457AB4 -> sub_45E940,发现关键代码

  1. sub_45A7BE("done!!! the flag is ");
  2. v5[0] = 18; v5[1] = 64; v5[2] = 98; v5[3] = 5; v5[4] = 2; v5[5] = 4; v5[6] = 6; v5[7] = 3; v5[8] = 6; v5[9] = 48; v5[10] = 49; v5[11] = 65; v5[12] = 32; v5[13] = 12; v5[14] = 48; v5[15] = 65; v5[16] = 31; v5[17] = 78; v5[18] = 62; v5[19] = 32; v5[20] = 49; v5[21] = 32; v5[22] = 1; v5[23] = 57; v5[24] = 96; v5[25] = 3; v5[26] = 21; v5[27] = 9; v5[28] = 4; v5[29] = 62; v5[30] = 3; v5[31] = 5; v5[32] = 4; v5[33] = 1; v5[34] = 2; v5[35] = 3; v5[36] = 44; v5[37] = 65; v5[38] = 78; v5[39] = 32; v5[40] = 16; v5[41] = 97; v5[42] = 54; v5[43] = 16; v5[44] = 44; v5[45] = 52; v5[46] = 32; v5[47] = 64; v5[48] = 89; v5[49] = 45; v5[50] = 32; v5[51] = 65; v5[52] = 15; v5[53] = 34; v5[54] = 18; v5[55] = 16; v5[56] = 0;
  3. v2[0] = 123; v2[1] = 32; v2[2] = 18; v2[3] = 98; v2[4] = 119; v2[5] = 108; v2[6] = 65; v2[7] = 41; v2[8] = 124; v2[9] = 80; v2[10] = 125; v2[11] = 38; v2[12] = 124; v2[13] = 111; v2[14] = 74; v2[15] = 49; v2[16] = 83; v2[17] = 108; v2[18] = 94; v2[19] = 108; v2[20] = 84; v2[21] = 6;
  4. for ( i = 0; i < 56; ++i ) {
  5. v2[i] ^= v5[i];
  6. v2[i] ^= 0x13u;
  7. }

编写程序求 flag

  1. v5 = [18, 64, 98, 5, 2, 4, 6, 3, 6, 48, 49, 65, 32, 12, 48, 65, 31, 78, 62, 32, 49, 32, 1, 57, 96, 3, 21, 9, 4, 62, 3, 5, 4, 1, 2, 3, 44, 65, 78, 32, 16, 97, 54, 16, 44, 52, 32, 64, 89, 45, 32, 65, 15, 34, 18, 16, 0]
  2. v2 = [123, 32, 18, 98, 119, 108, 65, 41, 124, 80, 125, 38, 124, 111, 74, 49, 83, 108, 94, 108, 84, 6, 96, 83, 44, 121, 104, 110, 32, 95, 117, 101, 99, 123, 127, 119, 96, 48, 107, 71, 92, 29, 81, 107, 90, 85, 64, 12, 43, 76, 86, 13, 114, 1, 117, 126]
  3. for i in range(56):
  4. v2[i] ^= v5[i]
  5. v2[i] ^= 0x13
  6. print(chr(v2[i]), end='')

zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t}

Hello, CTF(exe)

难度系数: 3.0 题目来源: Pediy CTF 2018 题目描述:菜鸡发现Flag似乎并不一定是明文比较的 题目场景: 暂无 题目附件: 附件1.exe

IDA 打开,F5 查看伪代码,发现关键代码

  1. int __cdecl main(int argc, const char **argv, const char **envp) {
  2. //...
  3. strcpy(v13, "437261636b4d654a757374466f7246756e");
  4. while ( 1 )
  5. {
  6. //...
  7. if ( !strcmp(v10, v13) )
  8. sub_40134B(aSuccess, v7);
  9. else
  10. sub_40134B(aWrong, v7);
  11. }
  12. //...
  13. }

Hex_to_ascii(437261636b4d654a757374466f7246756e) = CrackMeJustForFun

simple-unpack(elf)

难度系数: 4.0 题目来源: 暂无 题目描述:菜鸡拿到了一个被加壳的二进制文件 题目场景: 暂无 题目附件: 附件1

010Editor 打开发现是 ELF 文件,搜索 flag 得到 flag{Upx_1s_n0t_a_d3liv3r_c0mp4n†ß³Ûy}
flag 中不常见字符,提交也不对,说明被混淆了,拖到 exeinfope
image.png
看到有 upx 壳,用下面命令脱壳:
upx.exe -d 847be14b3e724782b658f2dda2e8045b

再用 010Editor 打开,搜索 flag 得到 flag{Upx_1s_n0t_a_d3liv3r_c0mp4ny}

logmein(elf)

难度系数: 4.0 题目来源: RC3 CTF 2016 题目描述:菜鸡开始接触一些基本的算法逆向了 题目场景: 暂无 题目附件: 附件1

拖入 exeinfope,发现是 64 位 elf
IDA 打开,发现关键代码

  1. void __fastcall __noreturn main(int a1, char **a2, char **a3)
  2. {
  3. size_t v3; // rsi
  4. int i; // [rsp+3Ch] [rbp-54h]
  5. char s[36]; // [rsp+40h] [rbp-50h] BYREF
  6. int v6; // [rsp+64h] [rbp-2Ch]
  7. __int64 v7; // [rsp+68h] [rbp-28h]
  8. char v8[28]; // [rsp+70h] [rbp-20h] BYREF
  9. int v9; // [rsp+8Ch] [rbp-4h]
  10. v9 = 0;
  11. strcpy(v8, ":\"AL_RT^L*.?+6/46");
  12. v7 = 0x65626D61726168LL;
  13. v6 = 7;
  14. printf("Welcome to the RC3 secure password guesser.\n");
  15. printf("To continue, you must enter the correct password.\n");
  16. printf("Enter your guess: ");
  17. __isoc99_scanf("%32s", s);
  18. v3 = strlen(s);
  19. if ( v3 < strlen(v8) )
  20. sub_4007C0(); // Incorrect password!
  21. for ( i = 0; i < strlen(s); ++i )
  22. {
  23. if ( i >= strlen(v8) )
  24. sub_4007C0(); // Incorrect password!
  25. if ( s[i] != (char)(*((_BYTE *)&v7 + i % v6) ^ v8[i]) )
  26. sub_4007C0(); // Incorrect password!
  27. }
  28. sub_4007F0(); // You entered the correct password!\nGreat job!
  29. }
  • 20-21 行:len(flag) >= len(':\"AL_RT^L*.?+6/46')
  • 24-25 行:len(flag) = len(':\"AL_RT^L*.?+6/46')
  • 26-27 行:flag[i] = chr(v7[i%7] ^ v8[i])
  • 13、27 行:(BYTE )v7 -> [0x68, 0x65, 0x62, 0x6D, 0x61, 0x72, 0x61](*注意是小端存储) -> 'harambe'

编写程序求 flag

  1. v7 = 'harambe'
  2. v8 = ':\"AL_RT^L*.?+6/46'
  3. for i in range(len(v8)):
  4. print(chr(ord(v7[i % 7]) ^ ord(v8[i])), end='')

flag:RC3-2016-XORISGUD

no-strings-attached(elf)

难度系数: 4.0 题目来源: 9447 CTF 2014 题目描述:菜鸡听说有的程序运行就能拿Flag? 题目场景: 暂无 题目附件: 附件1

32 位 elf,无壳,拖入 ida 反编译
image.png
main 函数

  1. int __cdecl main(int argc, const char **argv, const char **envp)
  2. {
  3. setlocale(6, &locale);
  4. banner();
  5. prompt_authentication();
  6. authenticate();
  7. return 0;
  8. }

分析 authenticate() 知 s2 存储 flag

  1. void authenticate()
  2. {
  3. wchar_t ws[8192]; // [esp+1Ch] [ebp-800Ch] BYREF
  4. wchar_t *s2; // [esp+801Ch] [ebp-Ch]
  5. s2 = (wchar_t *)decrypt((wchar_t *)&s, (wchar_t *)&dword_8048A90);
  6. if ( fgetws(ws, 0x2000, stdin) )
  7. {
  8. ws[wcslen(ws) - 1] = 0;
  9. if ( !wcscmp(ws, s2) ) // 比较ws和s2
  10. wprintf(&unk_8048B44); // Success!
  11. else
  12. wprintf(&unk_8048BA4); // Access denied!
  13. }
  14. free(s2);
  15. }

继续分析 decrypt() ,只需提取 s 和 a2 运算即可求 flag

  1. wchar_t *__cdecl decrypt(wchar_t *s, wchar_t *a2)
  2. {
  3. size_t v2; // eax
  4. signed int j; // [esp+1Ch] [ebp-1Ch]
  5. signed int i; // [esp+20h] [ebp-18h]
  6. signed int len_s; // [esp+24h] [ebp-14h]
  7. signed int len_a2; // [esp+28h] [ebp-10h]
  8. wchar_t *dest; // [esp+2Ch] [ebp-Ch]
  9. len_s = wcslen(s);
  10. len_a2 = wcslen(a2);
  11. v2 = wcslen(s);
  12. dest = (wchar_t *)malloc(v2 + 1);
  13. wcscpy(dest, s);
  14. while ( j < len_s )
  15. {
  16. for ( i = 0; i < len_a2 && j < len_s; ++i )
  17. dest[j++] -= a2[i];
  18. }
  19. return dest;
  20. }

shift-e 提取数据,末尾要去掉 4 字节
image.png
编写程序求 dest

  1. s = [
  2. 58, 20, 0, 0, 54, 20, 0, 0, 55, 20,
  3. 0, 0, 59, 20, 0, 0, 128, 20, 0, 0,
  4. 122, 20, 0, 0, 113, 20, 0, 0, 120, 20,
  5. 0, 0, 99, 20, 0, 0, 102, 20, 0, 0,
  6. 115, 20, 0, 0, 103, 20, 0, 0, 98, 20,
  7. 0, 0, 101, 20, 0, 0, 115, 20, 0, 0,
  8. 96, 20, 0, 0, 107, 20, 0, 0, 113, 20,
  9. 0, 0, 120, 20, 0, 0, 106, 20, 0, 0,
  10. 115, 20, 0, 0, 112, 20, 0, 0, 100, 20,
  11. 0, 0, 120, 20, 0, 0, 110, 20, 0, 0,
  12. 112, 20, 0, 0, 112, 20, 0, 0, 100, 20,
  13. 0, 0, 112, 20, 0, 0, 100, 20, 0, 0,
  14. 110, 20, 0, 0, 123, 20, 0, 0, 118, 20,
  15. 0, 0, 120, 20, 0, 0, 106, 20, 0, 0,
  16. 115, 20, 0, 0, 123, 20, 0, 0, 128, 20,
  17. 0, 0,
  18. ]
  19. a2 = [
  20. 1, 20, 0, 0, 2, 20, 0, 0, 3, 20,
  21. 0, 0, 4, 20, 0, 0, 5, 20, 0, 0,
  22. ]
  23. dest = s
  24. j = 0
  25. while j < len(s):
  26. i = 0
  27. while i < len(a2) and j < len(s):
  28. dest[j] -= a2[i]
  29. j += 1
  30. i += 1
  31. for b in dest:
  32. if b > 32:
  33. print(chr(b), end='')