吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3514|回复: 15
收起左侧

[CTF] 学破解第193天,《攻防世界reverse练习区re1-100》学习

  [复制链接]
小菜鸟一枚 发表于 2022-4-18 21:14

前言:

  坛友们,年轻就是资本,和我一起逆天改命吧,我的学习过程全部记录及学习资源:https://www.52pojie.cn/thread-1582287-1-1.html

立帖为证!--------记录学习的点点滴滴

0x1 收集信息

  1.首先,还是查壳,然后看一看文件格式,是windows平台还是linux平台的,是32位的,还是64位的。

https://s1.ax1x.com/2022/04/18/LdvZAU.png

  2.将文件复制到kali中,然后将ida目录下的linux_server64也复制过来,防止一会远程调试,先备用。

https://s1.ax1x.com/2022/04/18/LdxeqP.png

  3.运行一下程序,提示输入key,随便输入后提示wrong。

https://s1.ax1x.com/2022/04/18/LdxhJe.png

  4.现在小菜鸟已经收集到一下信息了:

1)目标是64位linux程序,没有加壳
2)程序流程是输入key进行校验
3)我的目的是找到正确的key

0x2 静态分析

  1.将程序拖进ida,找到main函数,F5可以看到伪代码:

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  __pid_t v3; // eax
  size_t v4; // rax
  ssize_t v5; // rbx
  bool v6; // al
  bool bCheckPtrace; // [rsp+13h] [rbp-1BDh]
  ssize_t numRead; // [rsp+18h] [rbp-1B8h]
  ssize_t numReada; // [rsp+18h] [rbp-1B8h]
  char bufWrite[200]; // [rsp+20h] [rbp-1B0h] BYREF
  char bufParentRead[200]; // [rsp+F0h] [rbp-E0h] BYREF
  unsigned __int64 v12; // [rsp+1B8h] [rbp-18h]

  v12 = __readfsqword(0x28u);
  bCheckPtrace = detectDebugging();
  if ( pipe(pParentWrite) == -1 )
    exit(1);
  if ( pipe(pParentRead) == -1 )
    exit(1);
  v3 = fork();
  if ( v3 != -1 )
  {
    if ( v3 )
    {
      close(pParentWrite[0]);
      close(pParentRead[1]);
      while ( 1 )
      {
        printf("Input key : ");
        memset(bufWrite, 0, sizeof(bufWrite));
        gets(bufWrite);
        v4 = strlen(bufWrite);
        v5 = write(pParentWrite[1], bufWrite, v4);
        if ( v5 != strlen(bufWrite) )
          printf("parent - partial/failed write");
        do
        {
          memset(bufParentRead, 0, sizeof(bufParentRead));
          numReada = read(pParentRead[0], bufParentRead, 0xC8uLL);
          v6 = bCheckPtrace || checkDebuggerProcessRunning();
          if ( !v6 && checkStringIsNumber(bufParentRead) && atoi(bufParentRead) )
          {
            puts("True");
            if ( close(pParentWrite[1]) == -1 )
              exit(1);
            exit(0);
          }
          puts("Wrong !!!\n");
        }
        while ( numReada == -1 );
      }
    }
    close(pParentWrite[1]);
    close(pParentRead[0]);
    while ( 1 )
    {
      memset(bufParentRead, 0, sizeof(bufParentRead));
      numRead = read(pParentWrite[0], bufParentRead, 0xC8uLL);
      if ( numRead == -1 )
        break;
      if ( numRead )
      {
        if ( !childCheckDebugResult()
          && bufParentRead[0] == 123
          && strlen(bufParentRead) == 42
          && !strncmp(&bufParentRead[1], "53fc275d81", 0xAuLL)
          && bufParentRead[strlen(bufParentRead) - 1] == 125
          && !strncmp(&bufParentRead[31], "4938ae4efd", 0xAuLL)
          && confuseKey(bufParentRead, 42)
          && !strncmp(bufParentRead, "{daf29f59034938ae4efd53fc275d81053ed5be8c}", 0x2AuLL) )
        {
          responseTrue();
        }
        else
        {
          responseFalse();
        }
      }
    }
    exit(1);
  }
  exit(1);
}

  2.看上去代码很多,先不慌,分段拆解,看这里面居然还有反调试checkDebuggerProcessRunning,找到wrong,看这里,似乎有点晕,提示wrong就循环,提示true就直接退出,那就说明这个if不该进去,直接把这段代码pass掉。

if ( !v6 && checkStringIsNumber(bufParentRead) && atoi(bufParentRead) )
          {
            puts("True");
            if ( close(pParentWrite[1]) == -1 )
              exit(1);
            exit(0);
          }
          puts("Wrong !!!\n");

  3.write和read是读文件和写文件,这里pParentWrite存储着我输入的字符串,pParentRead读取字符串。

printf("Input key : ");
        memset(bufWrite, 0, sizeof(bufWrite));
        gets(bufWrite);
        v4 = strlen(bufWrite);
        v5 = write(pParentWrite[1], bufWrite, v4);

memset(&s, 0, 0xC8uLL);
          v9 = read(pParentRead[0], &s, 0xC8uLL);

  4.继续往后翻,这里将pParentWrite里面的内容复制给s。

 memset(&s, 0, 0xC8uLL);
      v8 = read(pParentWrite[0], &s, 0xC8uLL);

  5.继续,看到关键的比较了,学数组的时候小菜鸟知道数组名就是数组首地址,这里先判断第一个字符是不是{,接着判断长度是不是42,然后晕圈,v12和v13咋来的?

if ( !(unsigned __int8)childCheckDebugResult()
          && s == 123
          && strlen(&s) == 42
          && !strncmp(v12, "53fc275d81", 0xAuLL)
          && *(&s + strlen(&s) - 1) == 125
          && !strncmp(v13, "4938ae4efd", 0xAuLL)
          && (unsigned __int8)confuseKey(&s, 42) == 1
          && !strncmp(&s, "{daf29f59034938ae4efd53fc275d81053ed5be8c}", 0x2AuLL) )
        {
          responseTrue();
        }
        else
        {
          responseFalse();
        }

  6.去反汇编窗口,按空格键,找到提示字符串,看到如下图所示信息,怀疑我的IDA F5反编译不准确,硬着头皮啃汇编吧,流程图中的汇编上面都是rbp+bufParentRead(我输入的字符串)进行比较,还是没看懂,重启IDA,出现一个提示框全勾上再说。

https://s1.ax1x.com/2022/04/18/LwV7OU.png

if ( !childCheckDebugResult()
          && bufParentRead[0] == 123
          && strlen(bufParentRead) == 42
          && !strncmp(&bufParentRead[1], "53fc275d81", 0xAuLL)
          && bufParentRead[strlen(bufParentRead) - 1] == 125
          && !strncmp(&bufParentRead[31], "4938ae4efd", 0xAuLL)
          && confuseKey(bufParentRead, 42)
          && !strncmp(bufParentRead, "{daf29f59034938ae4efd53fc275d81053ed5be8c}", 0x2AuLL) )

  7.这下子逻辑清晰了,输入字符串第一个字符必须是{,倒数第一个字符必须是},然后下标1-10对应的字符必须是"53fc275d81",下标31-40对应的字符必须是4938ae4efd,接着调用confuseKey函数将字符串变换,最后和{daf29f59034938ae4efd53fc275d81053ed5be8c}进行比较,看看confuseKey函数:

bool __cdecl confuseKey(char *szKey, int iKeyLength)
{
  char szPart1[15]; // [rsp+10h] [rbp-50h] BYREF
  char szPart2[15]; // [rsp+20h] [rbp-40h] BYREF
  char szPart3[15]; // [rsp+30h] [rbp-30h] BYREF
  char szPart4[15]; // [rsp+40h] [rbp-20h] BYREF
  unsigned __int64 v7; // [rsp+58h] [rbp-8h]

  v7 = __readfsqword(0x28u);
  *(_QWORD *)szPart1 = 0LL;
  *(_DWORD *)&szPart1[8] = 0;
  *(_WORD *)&szPart1[12] = 0;
  szPart1[14] = 0;
  *(_QWORD *)szPart2 = 0LL;
  *(_DWORD *)&szPart2[8] = 0;
  *(_WORD *)&szPart2[12] = 0;
  szPart2[14] = 0;
  *(_QWORD *)szPart3 = 0LL;
  *(_DWORD *)&szPart3[8] = 0;
  *(_WORD *)&szPart3[12] = 0;
  szPart3[14] = 0;
  *(_QWORD *)szPart4 = 0LL;
  *(_DWORD *)&szPart4[8] = 0;
  *(_WORD *)&szPart4[12] = 0;
  szPart4[14] = 0;
  if ( iKeyLength != 42 )
    return 0;
  if ( !szKey )
    return 0;
  if ( strlen(szKey) != 42 )
    return 0;
  if ( *szKey != 123 )
    return 0;
  strncpy(szPart1, szKey + 1, 0xAuLL);
  strncpy(szPart2, szKey + 11, 0xAuLL);
  strncpy(szPart3, szKey + 21, 0xAuLL);
  strncpy(szPart4, szKey + 31, 0xAuLL);
  memset(szKey, 0, 0x2AuLL);
  *szKey = 123;
  strcat(szKey, szPart3);
  strcat(szKey, szPart4);
  strcat(szKey, szPart1);
  strcat(szKey, szPart2);
  szKey[41] = 125;
  return 1;
}

  8.前面都没啥,主要看strncpy赋值语句和strcat字符串连接语句,可以看到把字符串分为4段,每段长度位10,然后按照3412的顺序进行连接,先看看替换后的字符串:

daf29f5903    第3段
4938ae4efd    第4段
53fc275d81    第1段
053ed5be8c    第2段

  9.调整顺序为1234得到key,{53fc275d81053ed5be8cdaf29f59034938ae4efd},运行程序验证一下,成功。

https://s1.ax1x.com/2022/04/18/LwnhHU.png

0x3 总结

  1.去攻防世界提交:flag{53fc275d81053ed5be8cdaf29f59034938ae4efd},居然提示错了,然后试{53fc275d81053ed5be8cdaf29f59034938ae4efd}还是错了,最后输入53fc275d81053ed5be8cdaf29f59034938ae4efd终于对了。

  2.这道题的逻辑其实很简单,主要是前面看伪代码懵圈了,然后想着IDA动态调试看参数的时候有点晕,一直断不下来,不知道是不是那个反调试的原因,真是奇了怪了。

免费评分

参与人数 8吾爱币 +12 热心值 +6 收起 理由
Hmily + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
xuhh + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
ZHANchenggu + 1 用心讨论,共获提升!
sinoit + 1 + 1 用心讨论,共获提升!
TuskAct4 + 1 + 1 谢谢@Thanks!
glz220 + 1 鼓励转贴优秀软件安全工具和文档!
44018723 + 2 很少见Linux的,支持!
lantianA + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

hackerbob 发表于 2022-4-24 22:07
风鸣雨喧 发表于 2022-4-19 17:50
学破解第164天,楼主学习记录导航贴更新!

楼主,这个帖子是不是该更新了下啊,你最新的都没有,只到187 ...

这个帖子在哪?
hackerbob 发表于 2022-4-24 22:41
风鸣雨喧 发表于 2022-4-24 22:39
点我前面发的那个文字(蓝色的)就直接跳转过去了,那是一个链接

感谢,非常感谢,最近想试试破解
wei5383079 发表于 2022-4-18 22:58
天天go 发表于 2022-4-19 08:27
非常不错。。。。。。。
贪恋毅世的浮华 发表于 2022-4-19 08:49
感谢分享
NBW666 发表于 2022-4-19 10:13
感谢分享,学习技术。
akhuoji 发表于 2022-4-19 10:45
大佬,厉害
o824 发表于 2022-4-19 11:29
感谢分享
LLJIZZ 发表于 2022-4-19 11:30
感谢分享,认真学习
Th52520 发表于 2022-4-19 16:19
感谢分享
风鸣雨喧 发表于 2022-4-19 17:50
学破解第164天,楼主学习记录导航贴更新!

楼主,这个帖子是不是该更新了下啊,你最新的都没有,只到187天,后面的呢?


免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
小菜鸟一枚 + 1 + 1 欢迎讨论,帖子被锁了,积累十篇以上再开新帖更新

查看全部评分

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-25 01:35

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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