Binary
unexploitable Writeup[pwnable.tw]

0x00 unexploitable

最近在刷pwnable.tw(类似pwnable.kr,不过是台湾的)的题,看到了一个unexploitable的题目。根据题目描述:

The original challenge is on pwnable.kr and it is solvable.
This time we fix the vulnerability and now we promise that the service is unexploitable.

下载下来后丢到ida看到确实没什么变化,除了pwnable.kr那个题中最重要的一点syscall没有给。

.text:0000000000400544 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:0000000000400544 public main
.text:0000000000400544 main proc near ; DATA XREF: _start+1Do
.text:0000000000400544
.text:0000000000400544 buf = byte ptr -10h
.text:0000000000400544
.text:0000000000400544 push rbp
.text:0000000000400545 mov rbp, rsp
.text:0000000000400548 sub rsp, 10h
.text:000000000040054C mov edi, 3 ; seconds
.text:0000000000400551 mov eax, 0
.text:0000000000400556 call _sleep
.text:000000000040055B lea rax, [rbp+buf]
.text:000000000040055F mov edx, 100h ; nbytes
.text:0000000000400564 mov rsi, rax ; buf
.text:0000000000400567 mov edi, 0 ; fd
.text:000000000040056C mov eax, 0
.text:0000000000400571 call _read
.text:0000000000400576 leave
.text:0000000000400577 retn
.text:0000000000400577 main endp
Linux如何搜索动态库

0x00 背景

在linux下安装一些程序,或者在做pwnable的时候经常出现没有找到动态库的情况。

mmap及linux地址空间随机化失效漏洞

Linux下动态库是通过mmap建立起内存和文件的映射关系。其定义如下void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset);,在第一个参数startNULL的时候系统会随机分配一个地址,我们可以通过示例来看mmap映射地址的流程。

分析一下程序加载libc.so的流程

open("/lib/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0 n\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1409436, ...}) = 0
mmap2(NULL, 1415560, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb75b1000
mmap2(0xb7705000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x154) = 0xb7705000
mmap2(0xb7708000, 10632, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7708000
close(3)

在通常情况下通过mmap映射的地址会被内核进行随机化处理,所以每次程序运行加载的动态库基址都不相同。

~ $ ldd mmap
linux-gate.so.1 => (0xb77d9000)
libc.so.6 => /lib/libc.so.6 (0xb7654000)
/lib/ld-linux.so.2 (0xb77bd000)
~ $ ldd mmap
linux-gate.so.1 => (0xb7738000)
libc.so.6 => /lib/libc.so.6 (0xb75b3000)
/lib/ld-linux.so.2 (0xb771c000)
dragon Writeup[pwnable.kr]

0x00 dragon

一个小游戏,我方可以选择牧师或者骑士(死亡骑士DK,23333),牧师的技能有

[ Priest ] 12 HP / 0 MP
[ 1 ] Holy Bolt [ Cost : 10 MP ]
Deals 20 Damage.
[ 2 ] Clarity [ Cost : 0 MP ]
Refreshes All Mana.
[ 3 ] HolyShield [ Cost: 25 MP ]
You Become Temporarily Invincible.

骑士的技能有

[ Knight ] 50 HP / 0 Mana
[ 1 ] Crash
Deals 20 Damage.
[ 2 ] Frenzy
Deals 40 Damage, But You Lose 20 HP.

然后对手是个怪兽,按照怪兽儿子,怪兽妈妈这样的顺序,然后正常打是打不过的。

md5 caculator Writeup[pwnable.kr]

0x00 md5 caculater

下载下来直接运行,提示缺libcrypto库,但是我却安装过了openssl。于是在lib下看,确实是没有这个库。因为我的环境是ubuntu x86_64装的openssl也是64位的,所以要安装32位的库,使用这个命令:

sudo apt-get install --reinstall libssl1.0.0:i386

安装好后反汇编一下,程序很简单。先生成一个随机数token,输入的值和随机数token相等则再输入一串base64编码后的文本,将这个文本解密后用md5加密打印。

tiny_easy Writeup[pwnable.kr]

0x00 tiny_easy

这个文件用sftp传下来看了一下,文件很小只有4k,代码也很少,直接执行则会报错。

python中Random的坑

0x00 前景提要

在搬砖过程中遇到一个巨坑,有一个python模块实现了一个本地监听多个端口的功能,为了防止监听端口冲突端口使用了python中的random模块中的randint函数来实现随机端口的生成。然而两次调用后却发现一直报error: [Errno 98] Address already in use,明显就是端口被占用。这个就比较奇怪了,因为该模块一次监听5个端口。怎么可能5个端口都会有冲突。

unexploitable Writeup[pwnable.kr]

0x00 unexploitable

看看源代码,很简单的程序

#include <stdio.h>
void main(){
// no brute forcing
sleep(3);
// exploit me
int buf[4];
read(0, buf, 1295);
}

第一反应是用return to dl reslove,但是仔细一看没法做内存泄漏。因为64位需要把debug位置0,但是无法得到link_map的地址,所以这条路走不通。只能在题目给出的syscall上做文章。

unlink Writeup[pwnable.kr]

unlink是堆溢出的常用思路,free一个堆时。有可能会调用unlink函数来拆卸freelist上堆块完成堆块的合并。如果能控制堆的控制区就有可能造成DWSHOOT(有限的任意地址写入)。

uaf Writeup[pwnable.kr]

0x00 UAF

UAF(Use After Free)释放后重用,其实是一种指针未置空造成的漏洞。在操作系统中,为了加快程序运行速度,如果释放一块n字节大小的内存空间,当申请一块同样大小的内存空间时,会将刚刚释放的内存空间重新分配。如果指向这块内存空间的指针没有置空,会造成一系列的问题。