安全矩阵

 找回密码
 立即注册
搜索
查看: 973|回复: 0

【逆向分析】BUUCTF 逆向题目 SimpleRev

[复制链接]

417

主题

417

帖子

2391

积分

金牌会员

Rank: 6Rank: 6

积分
2391
发表于 2023-12-7 18:22:41 | 显示全部楼层 |阅读模式
利刃信安 利刃信安攻防实验室 2023-12-02 19:01 发表于北京

题目地址:
  1. https://buuoj.cn/challenges#SimpleRev
复制代码


  1. https://files.buuoj.cn/files/7458c5c0ce999ac491df13cf7a7ed9f1/SimpleRev
复制代码




首先,查壳


  1. 信息:
  2.     文件名: H://BUUCTF/SimpleRev/SimpleRev
  3.     大小: 13128(12.82 KiB)
  4.     操作系统: Ubuntu Linux(ABI: 3.2.0)
  5.     架构: AMD64
  6.     模式: 64 位
  7.     类型: DYN
  8.     字节序: LE
复制代码


使用IDA64打开





F5






  1. unsigned __int64 Decry()
  2. {
  3.   char v1; // [rsp+Fh] [rbp-51h]
  4.   int v2; // [rsp+10h] [rbp-50h]
  5.   int v3; // [rsp+14h] [rbp-4Ch]
  6.   int i; // [rsp+18h] [rbp-48h]
  7.   int v5; // [rsp+1Ch] [rbp-44h]
  8.   char src[8]; // [rsp+20h] [rbp-40h] BYREF
  9.   __int64 v7; // [rsp+28h] [rbp-38h]
  10.   int v8; // [rsp+30h] [rbp-30h]
  11.   __int64 v9[2]; // [rsp+40h] [rbp-20h] BYREF
  12.   int v10; // [rsp+50h] [rbp-10h]
  13.   unsigned __int64 v11; // [rsp+58h] [rbp-8h]

  14.   v11 = __readfsqword('(');
  15.   *(_QWORD *)src = 'SLCDN';
  16.   v7 = 0LL;
  17.   v8 = 0;
  18.   v9[0] = 'wodah';
  19.   v9[1] = 0LL;
  20.   v10 = 0;
  21.   text = join(key3, (const char *)v9);
  22.   strcpy(key, key1);
  23.   strcat(key, src);
  24.   v2 = 0;
  25.   v3 = 0;
  26.   getchar();
  27.   v5 = strlen(key);
  28.   for ( i = 0; i < v5; ++i )
  29.   {
  30.     if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )
  31.       key[i] = key[v3 % v5] + 32;
  32.     ++v3;
  33.   }
  34.   printf("Please input your flag:");
  35.   while ( 1 )
  36.   {
  37.     v1 = getchar();
  38.     if ( v1 == '\n' )
  39.       break;
  40.     if ( v1 == ' ' )
  41.     {
  42.       ++v2;
  43.     }
  44.     else
  45.     {
  46.       if ( v1 <= '`' || v1 > 'z' )
  47.       {
  48.         if ( v1 > '@' && v1 <= 'Z' )
  49.         {
  50.           str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
  51.           ++v3;
  52.         }
  53.       }
  54.       else
  55.       {
  56.         str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
  57.         ++v3;
  58.       }
  59.       if ( !(v3 % v5) )
  60.         putchar(32);
  61.       ++v2;
  62.     }
  63.   }
  64.   if ( !strcmp(text, str2) )
  65.     puts("Congratulation!\n");
  66.   else
  67.     puts("Try again!\n");
  68.   return __readfsqword(0x28u) ^ v11;
  69. }
复制代码


这里涉及数据在内存中存储的方式大小端问题。

涉及大小端存储问题,elf文件这种通常使用小端存储,而IDA会把内存中的数据自动转成大端存储,但是有些变量双击过去,在文本视图能直接看到转好的字符串,以key3为例



而有些却不能,这个时候就需要自己把字符串倒过来,比如我们在伪代码看到的 str 是 SLCDN ,可实际用这个字符串的时候应该用 NDCLS 同理,wodah 改成 hadow 。

数据在内存中存储的方式:大端模式与小端模式

所谓的大端模式(Big-endian),是指数据的高字节,保存在内存的低地址中,而数据的低字节,保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;

所谓小端模式(Little-endian), 是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内在的低地址中,这种存储模式将地址的高低和数据位 权有效结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致;

假设一个十六进制数0x12345678

大端的存储方式是:12,34,56,78,然后读取的时候也是从前往后读

小端的存储方式是:78,56,34,12,然后读取的时候是从后往前读取

我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。


src = 'SLCDN' 则 src 小端存储 = 'NDCLS'

v9[0] = 'wodah' 则 v9[0] 小端存储 = 'hadow'



key1 = 'ADSFK'

key3 = 'kills'

text = join(key3, (const char *)v9) = 'killshadow'




key = 'ADSFKNDCLS'


上面的代码是将 key 的字符全部转成小写即 key = 'adsfkndcls'
分析str2



if ( !strcmp(text, str2) ) 由此段代码可知,当 str2 与 text 的字符串相同时,条件满足。这里可以得知,str2 是正确的 flag 经过一些列处理得到的,我们现在只需要把处理过程逆一下,就可以的到正确的 flag
用C++写脚本

  1. #include <stdio.h>
  2. #include <string.h>

  3. int main() {
  4.     int v3 = 0;
  5.     char key[] = "adsfkndcls";
  6.     char str2[] = "killshadow";
  7.     int v5 = strlen(key);

  8.     for (int v2 = 0; v2 < v5; v2++) {
  9.         for (int v1 = 'A'; v1 <= 'z'; v1++) {
  10.             if (str2[v2] == (v1 - 39 - key[v3 % v5] + 97) % 26 + 97) {
  11.                 printf("%c", v1);
  12.                 ++v3;
  13.                 break;
  14.             }
  15.         }
  16.     }
  17.    
  18.     return 0;
  19. }
复制代码



用Python3写脚本

  1. key = 'adsfkndcls'
  2. text = 'killshadow'
  3. v5 = len(key)
  4. flag = ''

  5. for v3, text_char in enumerate(text):
  6.     for v1 in range(65, 91):
  7.         if (v1 - 39 - ord(key[v3 % v5]) + 97) % 26 + 97 == ord(text_char):
  8.             flag += chr(v1)

  9. print(flag)
复制代码



运行结果为:KLDQCUDFZO
  1. flag{KLDQCUDFZO}
复制代码




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-27 22:31 , Processed in 0.012864 second(s), 19 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表