XCTF-pwn-hello_pwn

这几天在尝试入门,学习pwn的知识点,这是我关于pwn入门做的第一道题目,学习pwn需要很多的前置知识,并且需要一些环境,这里大概描述一下需要什么

  1. 拥有C语言基础
  2. 看懂简单的汇编代码
  3. 拥有一些python基础,需要使用到pwntools
  4. 拥有linux的基础,能够正常使用linux终端
  5. 简单熟悉ida

拥有上面的基础后,还需要一些pwn的环境:

  1. python环境
  2. ida free或者ida pro: 注意ida free是免费的,不过在反汇编成C语言代码的时候需要联网
  3. pwntools安装
  4. 安装pwndbg
  5. linux基础命令的使用gcc、checksec

对上述简单的了解以后,就可以进行简单的pwn题目了,在网上搜课的时候,大多数的师傅都说pwn的漏洞并不是很多,但是需要深入了解,入门难的原因时前置的知识要求高,虽然写这篇博客的时候,我也不太清楚为什么这个题目应该这样做,但是照着题目一点一点的做,不会的在网上搜,一点一点的就会变强,加油!

进入正题,首先我们启动靶机环境,然后题目给我们也提供了一个附件可以下载,这就是靶机端口上运行的服务

我们首先需要下载提供的附件,然后对该附件进行分析,最后得到想要的flag

下载后先使用mv命令将文件改名

然后使用file查看文件属性

上述中重要的信息有:

  • 该文件是一个64架构的ELF可执行文件
  • 该文件使用的库文件是动态链接(dynamically linked)

接着使用checksec命令查看该文件的安全保护机制,在最新版中需要使用--file=指定文件名,可以使用--help查看呢

这些安全机制还没有搞明白,慢慢学,但是比葫芦画瓢要知道这个步骤很重要

接着尝试运行一下该文件,手动的尝试分析,或者说感觉一下这个软件的功能

注意:有些时候在网上下载的ELF 可执行文件是没有执行权限了,使用ls -l可以看到文件是否有可执行(x)的权限,如果没有,使用chmod +x 文件名可以给该文件执行的权限

通过上述的分析,我们该程序进入的时候会输出~~ welcome to ctf ~~lets get helloworld for bof一段内容,这些不重要,重要的是该程序接受了我们用户的输入,一般程序出问题,都是对用于的输入没有进行严格的过滤和限制,导致程序出现漏洞或者bug,所以这里输出就是我们需要研究的地方

有了上述思路,使用ida freeflag文件打开,由于第一次,这里详细记录一下打开过程

上述图中有三个选项:

  • New就是打开一个新的程序分析
  • Go就是打开之前已经分析过的程序分析
  • 第三个还没学,暂时不了解

我们选择New然后调转到下面的页面

这是我们只需选择一个文件即可,这里选择flag文件,Open

然后会进入该页面

我们知道,有很多类型的可执行文件,例如windows中的exe、dll,这里就是选择可执行程序的类型,一般情况下,ida会自动分析程序的类型进行自动选择,这里我们可以不改变,点击OK即可

现在已经在分析flag程序了

该页面就是一个软件最基本的样式,占用页面最多的最多的就是汇编代码区域,这些都是ida分析该软件的特征模拟出的程序伪代码。在左侧显示该程序中执行代码,调用函数的基本流程。
摁下f5ida会将汇编代码转换为C语言代码

上述,在C语言基础中,我们知道程序运行所有的内容主要在main函数中,所以这里我们找到main函数查看该程序的运行逻辑

{
  alarm(0x3Cu);
  setbuf(stdout, 0LL);
  puts("~~ welcome to ctf ~~     ");
  puts("lets get helloworld for bof");
  read(0, &unk_601068, 0x10uLL);
  if ( dword_60106C == 1853186401 )
    sub_400686();
  return 0LL;
}

上述中C语言read()函数常用于读取文件描述符中的内容,常用的三个参数read(文件描述符,指针地址,大小),那么上述代码中0代表读取标准输入的值,也就是键盘输出的值,将输出的之复制给unk_601068这个变量的指针中,输入的内容大小最大为0x10uLL也就是十六进制16个字节uLL代表数据类型为无符号的长长整形

在下方进行了一个if语句的判断,如果dword_60106C变量的之和1853186401相等,那么执行sub_400686()函数,我们双击sub_400686()函数查看该函数的内容。

该函数会字节输出flag.txt的内容,这里我们知道,unk_601068是我们可以控制的,我们双击unk_601068该变量在内存中的地址

出上图中可以看出,unk_601068dword_60106C之差了四行,也就是四个字节,也可以使用计算器手动计算

这里一共可以获取我们输入的字节数为16个,所以这里可以利用read()溢出,

  1. 输出四个无用值占位,然后输出1853186401就可以替换dword_60106C变量的值,
  2. if调用dword_60106C变量时调用的是该变量的内存地址,也就是0x60106C,
  3. 然而这个内存地址的值已经被我们unk_601068变量的值通过read()函数溢出更改为1853186401,
  4. 最后该程序判断dword_60106C的值等于1853186401,输出flag

所以我们得思路就是连接靶机运行该脚本,然后输入四个aaaa,然后输入1853186401就对了

但是遗憾是,并没有获得flag,这里我们需要使用pwntools中的p32()函数获取我们传入的字符

可以看到为aaun,再次连接靶机,输入aaaaaaun即可获得flag

这里有一个疑问还有没有解决,为什么手动输入1853186401不行,虽然大概知为什么是错的,但是没有得到证实,不清楚其原理,这让我很难受。

posted @ 2023-11-30 09:49  Junglezt  阅读(23)  评论(0编辑  收藏  举报