title: ctfshow-REVERSE-刷题记录
tags:

  • ctfshow
  • RE
  • 记录
    abbrlink: 1bdb2719
    date: 2022-03-03 16:42:41

re2

打开初步分析为32位程序,无壳,拖入IDA32分析

ctfshow-REVERSE-刷题记录 - 图1

找到关键行47-50,分析得出各函数内部的基本作用如图所示

首先进入分析输入后的处理ctfshow-REVERSE-刷题记录 - 图2

可以很明显看出,是对输入的字符串进行处理后再操作,因此根据这个思路写出脚本,得到这里的密钥

  1. #!/usr/bin/python
  2. #coding=utf-8
  3. user = "DH~mqqvqxB^||zll@Jq~jkwpmvez{"
  4. flag = ''
  5. for x in range(0, 29):
  6. for y in range(256):
  7. if(ord(user[x])==y^0x1f):
  8. flag+=chr(y)
  9. print(flag) #[Warnning]Access_Unauthorized

接着分析加密函数,对加密函数内各函数分析后可得出大致为RC4,因此只要根据给出的加密内容进行逆向解密即可

ctfshow-REVERSE-刷题记录 - 图3

但是这里加密后的是什么内容是什么不清楚,我盲猜是给出的压缩文件里面的文本,但是这里没有科学依据,后来看到一篇大师傅的WP,他的分析是程序在最初会对enflag.txt的内容进行fopen() w操作,这样会清楚里面的文本,照此来看里面的东西其实没有被用过,因此可以推断他就是要加密的原始文本,因此在同目录下创建flag.txt,放入文本,解密成功。

ctfshow-REVERSE-刷题记录 - 图4

r2

打开后得到如下伪代码

  1. int __cdecl main(int argc, const char **argv, const char **envp)
  2. {
  3. size_t v3; // rax
  4. int v5; // [rsp+Ch] [rbp-134h] BYREF
  5. unsigned int i; // [rsp+10h] [rbp-130h]
  6. int v7; // [rsp+14h] [rbp-12Ch]
  7. int v8; // [rsp+18h] [rbp-128h]
  8. int v9; // [rsp+1Ch] [rbp-124h]
  9. int v10; // [rsp+20h] [rbp-120h]
  10. int v11; // [rsp+24h] [rbp-11Ch]
  11. int v12; // [rsp+28h] [rbp-118h]
  12. int v13; // [rsp+2Ch] [rbp-114h]
  13. int v14; // [rsp+30h] [rbp-110h]
  14. int v15; // [rsp+34h] [rbp-10Ch]
  15. unsigned __int64 v16; // [rsp+38h] [rbp-108h]
  16. int v17[8]; // [rsp+40h] [rbp-100h]
  17. char s[5]; // [rsp+60h] [rbp-E0h] BYREF
  18. char v19[107]; // [rsp+65h] [rbp-DBh] BYREF
  19. char dest[104]; // [rsp+D0h] [rbp-70h] BYREF
  20. unsigned __int64 v21; // [rsp+138h] [rbp-8h]
  21. v21 = __readfsqword(0x28u);
  22. v7 = 80;
  23. v8 = 64227;
  24. v9 = 226312059;
  25. v10 = -1540056586;
  26. v11 = 5;
  27. v12 = 16;
  28. v13 = 3833;
  29. v5 = 0;
  30. puts("plz input the key:");
  31. __isoc99_scanf("%s", s); // 输入key
  32. v3 = strlen(s); // 计算输入长度
  33. strncpy(dest, v19, v3 - 6); // 将s的6~strlen(s)-1位复制到dest,输入s的长度不小于6
  34. dest[strlen(s) - 6] = 0; // 最后1位置0
  35. __isoc99_sscanf(dest, "%x", &v5); // 读取dest中16进制数到v5
  36. v17[0] = v7;
  37. v17[1] = v8;
  38. v17[2] = v9;
  39. v17[3] = v10;
  40. v17[4] = (v11 << 12) + v12;
  41. v17[5] = v13;
  42. v17[6] = v5;
  43. v16 = 0LL;
  44. for ( i = 0; i <= 6; ++i )
  45. {
  46. for ( v16 += (unsigned int)v17[i]; v16 > 0xFFFF; v16 = v15 + (unsigned int)(unsigned __int16)v16 )// unsigned __int16只保留后4位
  47. {
  48. v14 = (unsigned __int16)v16; // 没用到v14,这行可以忽略
  49. v15 = v16 >> 16;
  50. }
  51. }
  52. if ( v16 == 0xFFFF )
  53. puts("OK");
  54. else
  55. puts("Error");
  56. return 0;
  57. }

从47行可见v16分别加上了v17的前6位,因此前6位是保持不变的,根据题意,v17[6]就是所要求的flag,所以这里可以写出如下程序

  1. #include<stdio.h>
  2. int main() {
  3. int v15 = 0;
  4. unsigned __int64 v16 = 0LL;
  5. int v17[7] = {80, 64227, 226312059, -1540056586, 20496, 3833, 888};
  6. for (int i = 0 ; i <= 6; ++i ) {
  7. for ( v16 += (unsigned int)v17[i]; v16 > 0xFFFF; v16 = v15 + (unsigned int)(unsigned __int16)v16 )
  8. v15 = v16 >> 16;
  9. }
  10. if ( v16 == 0xFFFF )
  11. puts("OK");
  12. else
  13. puts("Error");
  14. return 0;
  15. }

调试到即将与v17[6]相加的地方

ctfshow-REVERSE-刷题记录 - 图5

v16先加上v17[6],然后判断是否大于0xffff,小于等于0xffff即退出循环,由提示最小解,4位值,直接相减就可得出最终结果,最终得到flag即为flag{1a9f}

数学不及格_re3

用IDA打开,可以看到是一个类似于数学方程问题

ctfshow-REVERSE-刷题记录 - 图6

这里看到v9的值是v4经过函数f处理之后的值,再看一下函数f

ctfshow-REVERSE-刷题记录 - 图7

可以看出f函数是一个斐波那契的处理过程

这里的处理应当为四个判断等式联立求解,划掉v10-v12,得v4+3*v9;又因为v9为v4下标范围内的斐波拉契数列值,因此通过0<v4<200,有爆破可能性,直接遍历爆破v4与v9。(v4=58,v9=591286729879),后面依次求解v10-v12,并把它们转化为字符串,由此可写出python脚本

  1. def f(n):
  2. li=[]
  3. v9=0
  4. li.append(1)
  5. li.append(1)
  6. for i in range(2, n):
  7. li.append(li[i-1] + li[i-2])
  8. v9=li[i]
  9. return v9
  10. for i in range(1, 199):
  11. v4 = i
  12. v9=f(v4)
  13. if(v4+3*v9==151381742876+117138004530+155894355749+1349446086540):
  14. print(v4, v9)
  15. break
  16. v10 = hex(151381742876-v9)
  17. v11 = hex(117138004530-v9)
  18. v12 = hex(155894355749-v9)
  19. s='666c61677b6e65776265655f686572657d'
  20. flag=''
  21. for i in range(0, len(s), 2):
  22. flag+=chr(int(s[i:i+2], 16))
  23. print(flag)

可得出结果如下

ctfshow-REVERSE-刷题记录 - 图8

得到flag问题得解