首页 > 其他分享 >面向新手的CTF实战教学(一)

面向新手的CTF实战教学(一)

时间:2024-10-15 14:49:53浏览次数:10  
标签:实战 sub a1 CTF Str 字符串 新手 注册码 函数

一、初窥门径

首先,我们登录ctf.pediy.com,找到“2019看雪CTF晋级赛Q1”,然后就从第1关开始我们的夺旗之路吧。

第一关“流浪者”,题目要求输入正确的注册码。我们将程序下载下载后双击,会出现一个输入注册码的界面。此时我们随意输入一串字符并点击“验证”,程序会弹出一个消息框,提示我们输入错误。如图:

如果你曾有些逆向的入门知识的话,这算是逆向工程中最常见的场景了。按照常规的软件运行逻辑(获取输入的字符串 --> 对字符串进行处理 --> 与真正的注册码做比较  --> 如果正确则进行下一步、错误则弹出消息框),我们只需进行反向操作,即先根据消息框上面的文字,找到调用该消息框的函数,再通过层层回溯,找到处理字符串的关键函数,进而窥探出注册码的庐山真面目。那么在这里,我们需要记下消息框上的关键线索:“错了!加油!”,然后用反汇编软件对目标程序进行详细剖析。

二、庖丁解牛

在这里,我们使用著名的反汇编软件IDA ,首先打开IDA,载入目标程序。经过一番载入后,界面停在了程序的入口点: 

6.png

那么,我们下一步的任务,就是从目标程序里面找到我们记下的关键线索——那条叫做“错了!”的字符串。我们在 IDA 菜单栏中点选“View”-->“Open subview”-->“Strings”:

7.png

然后IDA界面上就显示出了目标程序内的字符串。看,里面有我们寻找的线索:

8双击.png

此时,我们双击该字符串,就来到了该字符串对应的位置(先不要管这个红色线框):

12.png

看到上图红色线框里面的字符“sub_4017B0”了吗?这就是引用“关键线索”字符串的函数,我们双击这个函数,来到了它的地址: 

13.png

从图中的汇编代码中可知,这是一个弹出消息框的函数,并不参与注册码的相关计算。再看红色线框的内容,是调用这个函数的“上家”函数sub_4017F0,我们且双击一下它,看看“上家”在搞什么鬼?

在双击过后,界面显示了sub_4017F0函数的地址:

14.png

哦……看看红色线框里面的内容,是在操作某些字符串!是不是感觉有了点眉目了?但这一堆压栈、读写寄存器等汇编指令看得人头大,我们在这个界面上按下键盘上的“F5”,IDA会将这个函数的汇编代码翻译为C语言风格的伪代码:

这下真相大白了,原来“上家”都干了这些事情!我们分析一下代码:

int __cdecl sub_4017F0(int a1)//传入一个int变量a1
{
  int result; // eax@6
  char Str1[28]; // [sp+D8h] [bp-24h]@4
  int v3; // [sp+F4h] [bp-8h]@1
  int v4; // [sp+F8h] [bp-4h]@1
 
  v4 = 0;
  v3 = 0;

//以a1的值为基础地址,每次累加4字节,读取对应的内存数据。由此可推断出a1是一个字符串的首地址,该字符串数
//据类型为DWORD,而1个DWORD所占空间为4字节,所以要以4的倍数来移动
  while ( *(_DWORD *)(a1 + 4 * v4) < 62 && *(_DWORD *)(a1 + 4 * v4) >= 0 )
  {
//将依次读取的a1[ ]的值作为aAbcdefghiabcde[ ]数组的下标,取得相应的值存入数组Str1[ ]中。
    Str1[v4] = aAbcdefghiabcde[*(_DWORD *)(a1 + 4 * v4)];
    ++v4;
  }
  Str1[v4] = 0;

//将Str1[ ]与"KanXueCTF2019JustForhappy"进行对比,如果相同则调用函数sub_401770(),如果不同则调用函数
//sub_4017B0(注意,这个就是之前弹报错消息框的函数)
  if ( !strcmp(Str1, "KanXueCTF2019JustForhappy") )
    result = sub_401770();
  else
    result = sub_4017B0();
  return result;
}

看到这里,我们就知道了,原来函数sub_4017F0是对某个叫a1[ ]的字符串当成了索引,用它来查阅aAbcdefghiabcde[ ]的内容,然后把查阅出来的内容与"KanXueCTF2019JustForhappy"进行对比。

那么,aAbcdefghiabcde[ ]数组里面的内容是啥呢?我们再次回顾到函数sub_4017F0的反汇编代码处:

19.png

哦,原来是“KanXueCTF2019JustForhappy”下面的那一串字符啊!注册码比对的原理搞明白了,胜利就在前方!

但是先别着急,还有最后一个问题:这个用来作对比的a1[ ]数组是从哪儿来的呢?是我们一开始输入到程序里的那串字符吗?还是有别的情况?带着这个疑惑,我们回到sub_4017F0函数的界面,发现该函数还有个“上家”sub_401890在调用它:

16.png

我们还用老办法,双击红色线框内的sub_401890,跳到这个函数。然后鼠标滚轮往上滚几下,来到函数的首地址00401890:

看,从反汇编代码中可以看出,这个函数要从程序的输入框中读取字符了!看来这就是计算注册码的第一个关口了。为了方便分析,我们继续用“F5”来读(伪)源代码:

18.png

坚持住,这是最后一步了!我们对代码进行分析:

//把输入的字符放到字符串数组Str[ ]中
  Str = CString::GetBuffer((CWnd *)((char *)v8 + 100), v3);

//遍历整个数组,对数组的值进行处理
 if ( strlen(Str) )
  {
    for ( i = 0; Str[i]; ++i )
    {
      if ( Str[i] > 57 || Str[i] < 48 )
      {
        if ( Str[i] > 122 || Str[i] < 97 )
        {
          if ( Str[i] > 90 || Str[i] < 65 )
            sub_4017B0();
          else
            v5[i] = Str[i] - 29;//如果Str[i]的元素的值在65~90之间,就把它减去29,将结果放到v5[i]中去;
        }
        else
        {
          v5[i] = Str[i] - 87;//如果Str[i]的元素的值在97~122之间,就把它减去29,将结果放到v5[i]中去;
        }
      }
      else
      {
        v5[i] = Str[i] - 48;//如果Str[i]的元素的值在57~48之间,就把它减去29,将结果放到v5[i]中去;
      }
    }
    result = sub_4017F0((int)v5);//将数组v5[]传递给函数sub_4017F0 ;
  }
  else
  {
    result = CWnd::MessageBoxA(v8, "请输入pass!", 0, 0);
  }
  return result;

从上面可以看出,函数sub_401890主要是对输入的字符的值进行逐个处理。如果字符的值在48~57之间,就将其减去48;如果在65~90之间,就将其减去29;如果在97~122之间,就将其减去87。然后将处理过的数组存放到v5[ ]里面。注意,这里面的值是ASCII码!通过查阅ASCII码表可以发现:48-57对应的是数字字符“0”~“9”,65-90对应的是大写字母“A”~“Z ”,97-122对应的是小写字母“a”~“z”。

综上所述,该程序的运行流程为:[双击启动程序 ]--> [输入注册码] --> [函数sub_401890获取注册码并进行处理]--> [将处理后的字符串传递给函数sub_4017F0函数,该函数以处理后的字符串数组为索引,从aAbcdefghiabcde[ ]里面查表] --> [如果查出的结果等于 “KanXueCTF2019JustForhappy”则通过,若不相等则报错]

三、见招拆招

知道了原理,那破译出注册码的算法也就简单了,我们只需要将其反向操作一下即可。

以“KanXueCTF2019JustForhappy”的第一个字符“K”为例,“K”字符在aAbcdefghiabcde[ ]字符串的第19个位置,(aAbcdefghiabcde[ ] =“abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQRSTUVWXYZ”,且数组第一个下标是以0为起点的),而且48~57减去48对应的值是[0~9];65~90减去29对应的值是[36~61];97~122减去87对应的值是[10~35];那么刚才“K”字符对应的19,落在了[10~35]的区间,可以得知“K”对应的注册码应该是19+87=106,通过查阅ASCII码可知,对应的是小写字母“j”。

那么,我们用编程来实现一下。上Python代码:

str_A = 'KanXueCTF2019JustForhappy'
str_B = 'abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQRSTUVWXYZ'
str_C = []
for i in str_A:
    str_C.append(str_B.index(i))
    
password = ''
for i in str_C:
    if i >= 0 and i <10:
        password += chr(i+48)
    if i >= 9 and i < 36:
        password += chr(i+87)
    if i >= 35 and i < 62:
        password += chr(i+29)
print(password)

运行结果如下:

21.png

看,注册码被计算出来了。这时我们把蓝色字符输入到程序中,CTF第一关就通过啦:

22.png

四、后记

其实第一关没有什么难度,但由于本文主要面向新手,所以重点讲解了IDA的基本操作 、字符串及函数的交叉引用、DWORD数据结构的存储原理 、简单的算法分析等一些基本功。随着第一关的顺利通过,我们稍事休息,在第二关见!

 

给大家的福利

零基础入门

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

1️⃣零基础入门

① 学习路线

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

② 路线对应学习视频

同时每个成长路线对应的板块都有配套的视频提供:

 因篇幅有限,仅展示部分资料

2️⃣视频配套资料&国内外网安书籍、文档

① 文档和书籍资料

② 黑客技术

因篇幅有限,仅展示部分资料

4️⃣网络安全面试题

5️⃣汇总

所有资料 ⚡️ ,朋友们如果有需要全套 《网络安全入门+进阶学习资源包》,扫码获取~

标签:实战,sub,a1,CTF,Str,字符串,新手,注册码,函数
From: https://blog.csdn.net/2301_76427295/article/details/142950065

相关文章

  • 开放式耳机品牌排行榜,新手必看开放式耳机的购买清单
    在科技不断发展的当下,开放式耳机成为音频设备领域的新宠。它既让我们能尽情享受音乐,又能使我们与外界保持联系,为我们带来独特的聆听体验。然而,市场上开放式耳机品牌众多,这让新手在选购时感到迷茫。为此,我们精心整理了这份“开放式耳机品牌排行榜,新手必看开放式耳机的购买清......
  • 【Next.js 项目实战系列】02-创建 Issue
    原文链接CSDN的排版/样式可能有问题,去我的博客查看原文系列吧,觉得有用的话,给我的库点个star,关注一下吧 上一篇【Next.js项目实战系列】01-创建项目创建Issue配置MySQL与Prisma​在数据库中可以找到相关内容,这里不再赘述添加model​本节代码链接#schema.pri......
  • 大模型新手指南:刷到让你少走三年弯路!
    这篇文章,我将结合自己在大模型领域的经验,给大家详细聊聊新人应该如何转行大模型赛道?比如大模型都有哪些方向?各方向的能力要求和岗位匹配?新手转行大模型常踩的坑和常见的误区?以及入行大模型最顺滑的路径?如果你是正打算入行大模型的校招/社招同学,请一定看完,可能会让你在入行......
  • basectf
    misc哇!珍德食泥鸭(wordxml隐写)题目是一个动图binwalk可以解压出很多东西通过打开文件发现里面的doucment.xml知道这个压缩包是docx文件,改名后进去发现这个图片其实没什么,我们可以发现这个文档特别长,但是往下拉啥都没有,这时候可以全选然后点击清除格式,拉到最后发现flagB......
  • 实战篇:(二)React 创建项目并连接 MySQL 后台的实战教程
    React创建项目并连接MySQL后台的实战教程一、项目概述本篇博客将介绍如何使用React搭建前端项目,并通过Node.js和MySQL实现简单的后台数据连接。通过这个项目,你将掌握从前端到后端数据库的基础开发流程,适合初学者或正在项目实战中的开发者。二、项目准备1.环境......
  • Moectf2024-All-Crypto
    前三周都出了,第四周有两题不会,为复现Crypto入门指北fromCrypto.Util.numberimportbytes_to_long,getPrimefromsecretimportflagp=getPrime(128)q=getPrime(128)n=p*qe=65537m=bytes_to_long(flag)c=pow(m,e,n)print(f"n={n}")print(f"p={p......
  • [SWPUCTF 2023 秋季新生赛]Shellcode WriteUp
    题目地址:https://www.nssctf.cn/problem/4546主要思路:利用Pwntools发送字节码调用执行execve("/bin/sh",NULL,NULL)实现要点:一定要添加context.binary='./shellcode'解释:pwntools的一个设置,用来指定目标二进制文件,以便于获取它的相关信息,如系统架构,操作系统类型等细节ex......
  • 小红书私域引流实战打粉手册(4)
       前言大家好,我是渡鸦科技社的联合创始人:南叔,操盘全网最大的引流截流圈子,精通各行业的流量玩法,为社群兄弟解决从前端引流到后端出现的各种实操问题。南叔把实战引流的经验总结出来,免费分享给大家,希望对大家有帮助。废话不多说,直接上干货上期回顾➡️➡️➡️小红书私域引流......
  • CTF 的基础知识 & 题型 & Trick总结
    references:12webphp语法基础references:1php脚本的基本格式:<?php//codinghere?>php代码同样以;结尾。php文件的后缀名大多是php,也有诸如php5php4phps之类,如果普通的后缀名被拦截不妨试试其他的。php变量用$来定义,大小写敏感,但是不用声明数据类型......
  • Web刷题之polarctf靶场(3)
    1.干正则打开靶场发现是简单的php代码审计,先构造id=a[0]=www.polarctf.com,由于要ping两次,所以先构造cmd=|ls<?phperror_reporting(0);if(empty($_GET['id'])){show_source(__FILE__);die();}else{include'flag.php';$a="www.baidu.com&q......