以前是照着题解做的,现在重新做一遍,发现存在许多问题。
题型专栏:
(1)PWN题型之Ret2libc
(2)PWN题型之对抗Canary保护技术
(3)PWN题型之栈迁移
程序分析:64位程序,没有开启任何保护。打开IDA,查看一下源代码

程序分析:main函数中只存在system("/bin/sh")函数,所以nc可直接拿到权限。nc(ip + 端口号)
程序分析:64位程序,没有开启任何保护。打开 IDA,查看一下源代码

代码分析:函数很简单,就一个puts函数输出,然后gets函数输入到s当中,用puts函数输出出来。
程序关键:存在gets函数,由于存在两个参数,准确来说是gets_s函数。(具体的请自行百度)
gets_s(buffer,size)函数:从标准输入中读取数据,size表示的最多读取的数量,在这里是argv,没有定义是多大,所以我们就可以无限的输入。但是可以发现buffer就只有0xF字节的大小,输入超过0xF个字节以后,你就会溢出,你会覆盖返回地址。所以如果你先填充字节,然后修改掉返回地址就可以调转到你想要跳转的地方。

存在溢出条件,接下来就是要找后门函数地址了。(为什么/bin/sh在前面,因为64位先传参数,其次找函数的地址就是找system函数以及它的参数)

发现system(“/bin/sh")函数地址,只要我们能控制程序返回到0x40118A,就可以得到系统的shell了
(5)exp:
程序分析 :32位程序,没有开启任何保护。打开 IDA,查看一下源代码。

代码分析:俩个write函数输出,然后sprintf函数利用%p将sub_40060函数地址(其实就是system函数)打印出来放到s里面,然后由write函数打印出来,由于是64位所以write那是9,
很容易发现了 gets函数,显然存在溢出条件,再查看是否存在后门函数。

发现了cat flag,只要我们能控制程序返回到0x000,就可以得到flag了。
下面就是找到偏移量,易得为0x40+8

exp:
程序分析:32位程序,只开启了NX保护,然后打开 IDA, 查看一下源代码

代码分析 :首先是一个fgets函数,从文件edata里面打印32个字节的内容到s里面,s可能存储0x3c(60)个字节,没有问题,之后就是一系列的c++语言了,(C++我也没有学,不是很懂)。大概意思就是会将 I 变成 you,这样就20个就等价于20个you这样就有60个字节了,这样就可以造成溢出了
运行 一下 程序,果然如此。
找到溢出条件后就要考虑偏移量和返回地址了


exp:
.
.
程序分析 :64位程序,只开启了NX保护 。然后打开IDA,查看一下程序源代码


程序分析:有一个gets函数输入v1的值,但是判断的却是v2是否与11.28125相等,只有相等就直接可以获得权限,所以要想办法绕过。
法一 :可以发现的是存在gets函数,加上本题没有开启canary保护,只要能找到cat flag地址就可以直接栈溢出到返回地址。
法二 :可以发现大小 v1<v2,gets函数 不限制 输入多少,所以它从30一直往下填充到返回地址,所以我们只要向下填充至v2时,然后将v2的内容 改成11.28125 就可以了。注意11.26125要改成16进制,这个在IDA中可以找到。
11.28125的十六进制:

(4)exp(1):
exp(2):
程序分析:64位程序,只开启了NX保护。打开IDA,查看一下源程序

代码分析 :就一个write函数和rea函数。可以发现read函数(这里buf只有0x80字节,而read需要从buf中读取0x200个字节),存在溢出条件。然后找是否存在后门函数

找到了system,是简单的栈溢出,找到偏移量为0x80+8,然后覆盖返回地址就可以了
exp:
程序分析 :64位程序,只开启了NX保护。打开IDA,查看一下源代码。

首先可以看到,我们只能输入1,输入2会一直在菜单里面循环,而输入其他的数值会直接退出去。打开encrypt函数

存在gets函数,但是它不能直接溢出,因为后面的while循里有s[x] ^= 0xFu系列,这样导致你输入的s的数值发生了变化,你输入的payload就会改变。为了避免执行循环,要在payload最前面加入‘0’,这和strlen函数有关,strlen函数遇到‘0’就会停止,这样值为0.,而v0 = x,x为无符号整型大于等于0,所以判断为真就能避免执行while循环。
payload:
offset = 0x50 + 8 - 1
payload1 = ‘0’+ offset*‘a’ + p64(rdi_addr_ret) + p64(puts_got_addr) + p64(puts_plt_addr) + p64(main_addr)
r.sendline( payload1)
找到溢出条件以后,就是找后门函数了,不存在又开启了nx保护,libc泄露地址。
exp :
程序分析:32位程序,只开启了NX保护。打开IDA,查看源代码
可以发现read函数,从/dev/unandom 目录下的fd文件中读取四字节的内容。(随机数)
接着可以看到三个主要函数,打开第一个没有发现什么,打开第二个71F函数

发现存在read函数,也没有达到溢出条件,存在strncmp函数,两者进行比较,由于一个是随机生成的数组,那必然不会相等,而只要不是0就会执行if,然后就会退出程序。所有就要么修改随机数值要么就让比较的字符串为0(第三个参数值为0)。

而在此之前,我们能做的就是输入buf的内容,根据strlen函数的性质,buf只要最开始输入的就是’0’就会直接退出去,这样v1就为0,就不会进行strcmp比较。

然后就是返回值是buf[7] = v2,然后作为参数传给_7D0函数,再看第三个函数

又是两个read函数,第一个read明显可能不可能溢出。但是第二个却是有可能:因为a1是参数是由v2传进来的,而v2等于上一个函数的返回值,即a1 = v2 = buf[7],而buf是由我们写入的。只要buf第八个数值足够大就可以使得read函数溢出。
构造payload:
exp :
程序分析:32位程序,开启了canary保护和NX保护。打开IDA,查看一下源代码

存在格式化字符串漏洞,利用它任意写的特点。将随机数改成一个常数,然后输入这个常数就能获得flag了。
做这种题首先是要确定格式化字符串的位置
可以发现格式化字符串在第十个
exp :
程序分析:32位程序,开启了NX保护。打开IDA,查看一下源代码

存在gets函数 存在溢出条件,但是gets函数里面一大串内容,那必然没有那么简单,函数很乱没看懂。于是先暂时不管它
后面本地调试发现可以通过而远程连接却不行。有大佬说是:由于这题没有出现setbuf(stdin,0),所以本题的输出是缓存在服务器本地的,换句话说:如果程序不正常退出,本题是不会回显flag的。
存在溢出条件,接下来就是寻找后门函数了

存在“flag.txt”文件,并且后门的是rt

所以只要先溢出,然后修改返回值跳到该函数,修改两个参数a1和a2,就可以活得flag了,而远程的话需要添加一个exit地址强制退出程序。
exp :
注意:一般我们都是直接用ida里面的偏移量,但是有时候这个是错的,所以需要我们用gdb来查看。我用的是peda插件(里面的偏移量是达到ret的):


这道题和 第七题的ciscn_2019_c_1 一模一样,直接cv脚本就可以了。
程序分析:32位程序,开启了NX和canary保护。打开IDA,查看一下源代码

首先就发现了system(/bin/sh)函数,看看条件:只有var【13】 = 17就可以了。而看前面的scanf就可以向var数组输入。我们只要将var这个数组里全部填上17即可。至于后面的两个参数我觉得应该是ida编译问题。
exp:
程序分析:32位程序,开启了NX保护,打开 IDA, 查看一下源代码

发现存在read函数,存在溢出。又看到了system函数,但是缺少/bin/sh参数,寻找是否存在。

找到了system函数,/bin/sh参数,以及溢出条件。明显栈溢出
exp :
程序分析:32位程序,开启了NX保护,打开 IDA, 查看一下源代码

可以发现gets函数,明显存在溢出条件。但是打开gets函数里面很复杂(感觉不简单)。再查看一下后门函数

可以发现和get_started_3dsctf_2016类似,差别就是这道题没有读取文件的命令所以需要你用write函数将这个文件打印出来。
exp分析:
payload = offset*‘a’ + p32(get_flag_addr) + p32(write_addr) + p32(eixt_addr)+ p32(1) + p32(flag_addr) + p32(0x100)
先填充完字节后跳到get_secret函数里面(里面有flag文件)。然后用write函数读取flag文件(因为他只是一个文件,没有cat读取)。然后exit函数(因为这道题没有setbuf(stdin,0),所以本题的输出是缓存在服务器本地的,即程序不能正常退出)。接下来就是write函数的三个参数。第二个为要读取内容。
程序分析:64位程序,开启了NX保护,打开 IDA, 查看一下源代码

首先scanf输入nbytes的值,然后再是输入read函数,而scanf输入的正好是read的第三个参数。只要输入大于0x10+8就能覆盖返回地址了。找到溢出条件。

在backdoor函数里面存在system函数。找到溢出条件,system函数,构造exp
exp :
程序分析:64位程序,开启了NX保护,打开 IDA, 查看一下源代码

只有一个scanf输入v4的值,scanf不限制输入,再查看字符串,看看是否存在后门函数地址。
发现了system函数和字符串/bin/sh
payload = offset * ‘a’ + p64(rdi_addr) + p64(binsh_addr) + p64(system_addr)
exp :
不过到现在还是不知道为啥本地跑不通,远程可以跑通。
程序分析:64位程序,开启了NX保护,打开 IDA, 查看一下源代码

显然可以发现system函数,但是没有/bin/sh 参数,存在read函数,明显溢出了,然后找找是否存在/bin/sh参数

存system(/bin/sh),溢出条件,没有开启canary保护。直接溢出覆盖返回地址。但是这是64位,与32位存在差别。64位的传参顺序不同
exp :
程序分析:64位程序,没有开启任何保护,打开 IDA, 查看伪代码

代码分析:存在read函数输出你的名字,存在gets函数明显栈溢出。shift + f12查看是否存在后门函数

没有system函数,由于这道题没有开启NX保护,
1.可以直接构造shellcode(与system函数作用类似)。shellcode = asm(shellcraft.sh()光构造出来了还不行,需要你存放在一个地址上。而前面你需要输入你的名字,而name的地址在bss段,永远不会变,即输入name时将构造的shellcode存放里面

2.直接利用libc泄露system函数,不过这道题没有开启NX保护,这样写倒是麻烦了一些。
exp :
程序分析:32位程序,开启了NX保护,打开 IDA, 查看一下源代码

可以发现在main处按f5无法打开反汇编。这样的话你多点击一下其他函数,然后f5就可以看了

首先可以看到第一个scanf要输入administrator,否则就会直接退出。
然后又是一个scanf函数输入,这下面有五种case,一一打开case里面的函数。可以发现重点是1和4。

在case1函数下面存在scanf函数,根据 可知传入的参数为scr,a1 = src。避免混淆你可以按n将a1改为src。在这里你可以写入scr的内容

接着打开GetFlag函数,可以发现存在strcpy函数。

根据前面可知:src的大小和内容其实是由我们自己控制的,这样的话只要我们输入的字符串够大(大于0x48+4)就会造成strcpy函数溢出。所以直接在1里面构造payload
整合起来其实就是输入src,然后造成strcpy函数溢出
注意 :break只是结束当前的一次循环,所以case1以后只会结束switch循环,不会结束while循环,而while(1)一直成立,所以它会继续让你选择case,但是你修改返回地址以后就停止了。
找到溢出条件以后,找后门地址。

exp :
程序分析:32位程序,开启了NX保护,打开 IDA, 查看一下源代码

存在read函数溢出,接下来查看是否存在后门地址
没有发现,由于开启了NX保护,这是一道基本的libc题
程序分析:32位程序,开启了NX保护,打开 IDA, 查看一下源代码

存在execve,11,int 80h等字眼,感觉就像是系统调用system函数。

查看一下汇编代码,果然是这样,既然直接调用了system函数,那么直接nc就可以获得flag了。不过由于使用汇编语言写的,可能就没那么容易理解了。
程序分析:64位程序,开启了NX保护,打开 IDA, 查看一下源代码

在vuln函数里面存在read函数,存在溢出条件,然后找是否存在后门地址
程序分析:32位程序,开启了NX保护,打开 IDA, 查看一下源代码

代码分析:首先get_n函数输入nptr的值,四个字节,然后atoi将nptr转换为整数型,不过输入的整数不能大于32,不然就会强制退出,然后又是get函数输入,大小是v2,而nptr只能存储0x2C个字节。v2是由我们自己输入的,那是不是可以将v2大小写大一点,然后后一个get函数溢出呢?但是考虑到v2最大只能是32又不行,这个时候就要考虑atoi函数了。

这个函数的作用大概就是把最前面的数字截取出来,如果最开始是字符则返回值直接为0,如果是数字的话则返回该数字,返回值为整数型,说明可以是为负数。这样的话由于在get函数里面会强制转换成正数,主要我们只要输入一个负数,它既满足大小小于32,又能导致后一个get函数溢出。

通过运行一下程序看看是不是会强制转换:
果然-1会变成,找到了溢出条。接下来我们寻找发现不存在system函数。需要利用libc泄露system地址了。
exp :
注意点:
1.由于这里没有write,puts函数,所以我用的是printf函数泄露,而printf函数的第一个参数格式化字符串,所以需要找到一个带有%s的地址。
payload = offset * ‘a’ + p32(printf_plt_addr) + p32(main_addr) + p32(format_addr) + p32(printf_got_addr)
2.由于recv接收的时候并不是最开始的四个字节,所以需要改写接收方式。这个是我自己调试试出来的,需要接受四个字节,可能会有其他简写方法。
printf_addr = u32(r.recvuntil("xf7")[-4:].ljust(4,"x00"))
程序分析:32位程序,开启了NX保护,打开 IDA, 查看一下源代码

可以明显的看到格式化字符串漏洞,并且当x等于4时就可以获得权限。所以这道题的思路就是利用格式化字符串漏洞的任意写功能修改x的值为4。
exp:
程序分析:32位程序,开启了NX保护,打开 IDA, 查看一下伪代码
可以发现存在read函数溢出,查看是否存在后门函数。发现并不存在,利用libc泄露system函数地址。
exp:
程序分析:64位程序,开启了NX保护,打开 IDA, 查看一下源代码

存在read函数溢出,再查看是否存在后门地址。没有发现system函数,利用libc泄露system函数了
注意:
find -name “flag”
exp:
详细请看 : 栈迁移
程序分析:32位程序,开启了NX保护,打开 IDA, 查看一下源代码

可以发现read函数构成溢出条件,但是其大小只能刚刚好覆盖返回地址。只于后面的参数之类的地址却缺少了空间。
对于这种情况,师傅们采用了栈迁移的方法,类似扩充大小。将剩下未写入的放在其他空间中。具体的请自行百度(毕竟我还不是完全弄懂)
接下来就是找后门函数,可以发现这题没有。所以用libc泄露system函数地址。
exp :
程序分析:64位程序,开启了NX保护,然后打开 IDA, 查看一下源代码

存在溢出条件(read函数溢出),查看是否存在后后门地址

在good_game里面存在flag.txt。找到溢出条件和后门地址以后就可以写exp了。不过这道题的偏移量在IDA里面是错误的。需要在gdb里面找了,这个可以看https://blog.csdn.net/m0_/article/details/
exp:
程序分析:64位程序,开启了NX保护,然后打开 IDA, 查看一下源代码

可以发现这里存在数据强行转换。只要你输入一个负数,unsigned int就会强行转换成正数。而前面是signed不会转换,不会执行if。
不过这里需要注意的是:远程可以跑通,但是本地跑不通
程序分析:32位程序,开启了NX保护,然后打开 IDA, 查看一下源代码

程序代码简单,存在溢出条件。shift+f12没有后门地址。开启了NX保护。l所以用ibc泄露system函数。
exp :
exp分析 :
write_offset = 0x000D43C0
system_offset = 0x0003A940
binsh_offset = 0x0015902b
这里的write函数偏移地址和system偏移地址可以在buuctf里面给出的lib文件找。而binsh参数需要在linux里面利用libc版本找了,具体操作:
程序分析:64位程序,开启了NX保护,然后打开 IDA, 查看一下源代码

程序源代码简单,存在read溢出条件。查找字符串没有发现后门地址,开启了NX保护,利用libc泄露system函数地址
exp :
exp分析 :
payload1 = offset*‘a’ + p64(rdi_addr_ret) + p64(1) + p64(rsi_addr_ret) + p64(write_got_addr) + p64(0) + p64(write_plt_addr) + p64(main_addr)
64位和32位的传参不同,64位有6个参数,它会先进行传参,传参时需要先找到位置。像这道题是利用write函数泄露write函数真正的地址。write函数有三个参数,所以先传三个参数,找地址的方式为
第一个参数存放在rdi中,存放内容为1,第二个参数存放在rsi中,内容为write函数的真正地址,至于第三个参数地址是可以不需要的,因为write函数第三个是存放的是输出大小,管他随机是多少。接下来就是返回地址·,然后是预留返回地址。
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.mushiming.com/mjsbk/3773.html