每日一pwn[ciscn_2019_c_1]
每日一pwn[ciscn_2019_c_1]前言存在栈溢出漏洞,无后门函数,存在一个加密函数,但是对payload无影响
分析
关键函数,存在一个栈溢出,但是发现存在一个对我们输入的数据进行加密的流程,本来以为需要逆向一下代码,发现在strlen函数那里存在一个截断,于是便不需要对payload进行更改,直接使用即可
漏洞点存在一个栈溢出,直接打一个puts函数泄露基地址,然后ogg获得shell
EXP12345678910111213141516def exploit(): li('exploit...') db() ogg = 0x4f322 puts_got = 0x000000000602020 puts_plt = 0x0000000004006E0 pop_rdi_ret = 0x0000000000400c83 pl = "A"*0x50+p64(0xbadbeef)+p64(pop_rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(0x000000000 ...
检测是否存在于沙箱中
检测是否存在于沙箱中检测运行时间CPUID上述的几种方法都是基于延时执行或者由其引出的一些特性来进行沙箱检测的。由于虚拟化自身的特性,也会造成某些指令的执行在虚拟环境和真实环境中有时间差异。
得益于Hypervisor的普及,许多作弊软件制作者利用虚拟化技术逃避了反作弊引擎的检测。与此对应,反作弊引擎的厂商也没有坐以待毙,研究出了一系列检测虚拟化的方法。接下来要介绍的就是来自BattlEye的反沙箱方法。
原理:首先我们要知道CPUID是什么,它为什么能够作为检测沙箱的指标:CPUID 在真实硬件上是一条相对快捷的指令,通常只需要 200 个周期,而在虚拟化环境中,由于内省引擎产生的开销,它可能需要十倍甚至更多的时间。
12345678910111213141516171819unsigned __int64 old_priority = SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); unsigned __int64 rdtsc_first = __rdtsc();Sleep(2000);un ...
格式化字符串漏洞
格式化字符串漏洞初学pwn,学到了格式化字符串漏洞,总结一下。
格式化字符串函数:格式化字符串函数就是将计算机内存中表示的数据转化为我们人类可读的字符串格式。
漏洞printf(s)
用 printf() 为例,它的第一个参数就是格式化字符串 :”Color %s,Number %d,Float %4.2f”
然后 printf 函数会根据这个格式化字符串来解析对应的其他参数
%d - 十进制 - 输出十进制整数
%s - 字符串 - 从内存中读取字符串
%x - 十六进制 - 输出十六进制数
%c - 字符 - 输出字符
%p - 指针 - 指针地址
%n - 到目前为止所写的字符数
%hhn - 写1字节
%hn - 写2字节
%ln - 写4个字节
%lln - 写8字节
格式转换格式化字符串是由普通字符(包括%)和转换规则构成的字符序列。普通字符被原封不动地复制到输出流中。转换规则根据与实参对应的转换指示符对其进行转换,然后将结果写入到输出流中。
转换规则由可选的部分和必选部分组成。其中只有转换指示符type是必选部分,用来表示转换类型。
可选部分如下:
可 ...
格式化字符串在堆上的利用
格式化字符串在堆上的利用前言在面试星盟的时候,面试的师傅考到了这个问题。才明白过来,其实自己对于格式化字符串的理解还是太浅了。于是就按照书上的教程又学习了一下
格式化字符串不在栈上的利用方式所谓堆上的格式化字符串指的是格式化字符串本身存储在堆上,这个主要增加了我们获取对应偏移的难度,而一般来说,该格式化字符串都是很有可能被复制到栈上的。
本来一般的格式化字符串是可以通过栈的压栈传参来控制后面的数据,达到任意地址写和任意地址读的,但是在堆上的,我们便无法去控制这些数据
于是我们就有了新的利用方法,通过在栈上三重指针p1 -> p2 -> p3 , 通过p1 去控制p2 的指针,然后我们就可以通过p2的指针去控制p3的值,于是我们便可以在p3上写入地址,然后通过p3指针去修改值。
下面是书上的源文件
1234567891011121314151617181920212223242526272829303132333435#include<stdio.h>#include<unistd.h>void init(){ setbuf(stdi ...
栈迁移面试做题复现
栈迁移面试做题复现前言在面试星盟安全的时候,遇到一道栈迁移的题,因为好久没做题了,花了很久的时间才做出来,现在专门写一篇博客记录一下
栈迁移栈迁移主要就是在恢复栈地址后,返回到leave继续恢复,就能够根据我们覆盖的ebp的值去将栈偏移过去,也就是可以将执行流给转移过去。最主要的利用难度就是如何控制迁移过去的地址上面的值,
一种是泄露当前ebp的值然后栈迁移到当前栈地址的前面,利用我们写进去的脏数据来ROP,
还有一种就是利用read和一些现成的其他函数去控制对应地址,这里一般就是转移到bss段去控制(bss段含有一些其他的数据,在后面执行函数的时候可能会有影响,所以我们一般选取具有写权限的高地址的地址)
题目详情
这里由于汇编较为简单,于是我就直接放的汇编。
没有开启pie保护,没有system函数,于是需要泄露libc地址
这里存在栈溢出漏洞,但只允许溢出16个字节
于是我们考虑栈迁移
但是没有其他函数泄露ebp的地址,于是我们可以利用现成的read函数,可以看到read函数的rsi是由rbp-0x60控制的,于是我们控制ebp即可,就可以控制ebp-0x60地址上的值
再在eb ...
栈迁移技术-PWN
栈迁移技术-PWN
本文将对CTF Pwn中「栈迁移」(又称「栈转移」)这一技术进行介绍与分析,希望读完本文后以下问题将不再困扰你:
什么是栈迁移?
栈迁移解决了什么问题?
怎么使用栈迁移这个技巧?
开始之前,有如下预备知识会极大提升你的阅读体验:
CTF Pwn是在做什么?提权(Getshell)是什么意思?
在操作系统内存布局中,栈是一种怎样的结构,具有怎样的特点?
x86中常用寄存器的名称与作用?函数调用栈的原理与过程是怎样的?
栈溢出攻击的核心技巧是什么?
栈溢出是怎么回事?在预备知识的4个问题中,也许第四个会困扰到你。其实,如果知道了前三个问题的答案,联想编程时偶尔出现的「 Error:Index out of bound」报错,栈溢出(stackoverflow)是怎么一回事也非常简单了。下图是一个函数栈布局的常见状态。
顾名思义,栈溢出就是当外界输入过长时,将会超过局部变量(常为数组)的「势力范围」,从而造成数据溢出;如下图所示。
因此,栈溢出能使我们覆盖栈上某些区域的值,甚至是当前函数的返回地址 ret ;一旦 ret 覆盖为某个奇怪的值,例如 ...
栈溢出计算偏移量
栈溢出计算偏移量一,GDB调试出偏移量1230x8048677 <main+95> lea eax, [esp + 0x1c] 0x804867b <main+99> mov dword ptr [esp], eax► 0x804867e <main+102> call gets@plt
通过这一串汇编指令可以看出来,此时起始地址相对于esp的偏移为0x1c,只要查看这时候的esp和ebp的寄存器就可以知道偏移量为多少。
12EBP 0xffffcfb8 ◂— 0x0ESP 0xffffcf30 —▸ 0xffffcf4c ◂— 0x0
这里就可以算出来起始地址相对于返回地址的偏移为0xffffcfb8 - 0xffffcf30 - 0x1c + 4。为112。这里的加四为ebp的值,在返回地址前还有一个ebp的值也要覆盖。
二,GDB-peda计算偏移量
使用gdb运行程序
gdb ./pwn
生成溢出字符串
($gdb-peda) pattern create 200
长度需要保证可以 ...
栈溢出保护原理——Stack Canaries
栈溢出保护原理——Stack CanariesStack Canaries (取名自地下煤矿的金丝雀,因为它能比矿工更早地发现煤气泄露,有预警的作用)
是一种对抗栈溢出攻击的技术,即SSP安全机制
Canary的值是栈上的一个随机数,在程序启动时随机生成并保存在比函数返回地址更低的位置。由于栈溢出是从低地址向高地址进行覆盖,因此攻击者要想控制函数的返回指针,就一定要先覆盖到Canary。程序只需要在函数返回前检查Canary是否被篡改,就可以达到保护栈的目的。
一,Canaries的分类canaries 通常可分为3类:terminator,random 和random XOR,具体的实现有StackGuard,StackShield,proPoliced等。
Terminator canaries:由于许多栈溢出都是由于字符串操作(如strcpy)不当所产生的,而这些字符串由NULL“\x00”结尾,换个角度看就是会被“\x00”所截断。基于这一点,terminator canaries将低位设置为“\x00”,既可以防止被泄露,也可以防止被伪造,截断字符还包括CR(0x0d ...
栈是数据结构的一种
栈是数据结构的一种
条件竞争的利用
条件竞争的利用构造例子源代码源代码如下
已复制
12345678910111213141516171819202122232425262728293031323334353637383940414243444546#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/stat.h>#include <unistd.h>void showflag() { system("cat flag"); }void vuln(char *file, char *buf) { int number; int index = 0; int fd = open(file, O_RDONLY); if (fd == -1) { perror("open file failed!!"); return; } ...