醉梦半醒的博客

pwn学习笔记

字数统计: 354阅读时长: 1 min
2019/05/05 Share

pwntools常用指令
p64(int) 8个bite为一组,最小的放前面,依次排列
u64(str) 上面的逆过程
p32(int)
u32(str)
remote(host, port) / process(path)
.recv(int) 7 => Hello world! => ‘Hello w’
.recvuntil(str) ‘or’ => Hello world! => ‘Hello wor’
.recvline() === .recvuntil(‘\n’)
.send(str) ‘payload’ => ‘payload’
.sendline(str) ‘payload’ => ‘payload\n’
.interactive()

例1

1
2
3
4
5
6
7
8
9
10
11
from pwn import *
r=process('./pwntools')
r.recvuntil(':)\n');
r.send(p32(3735928559))
r.recvuntil('seconds!!!\n')
for i in range(1000):
s = r.recvuntil('?').replace(' = ?', '')
print s
ans = eval(s)
r.sendline(str(ans))
r.interactive()

ELF header


x64 Calling Convention
微软x64调用约定使用%rdi, %rsi, %rdx, %rcx,%r8, %r9 六个寄存器用于存储函数调用时的6个参数(从左到右),使用XMM0, XMM1, XMM2, XMM3来传递浮点变量。其他的参数直接入栈(从右至左)。整型返回值放置在RAX中,浮点返回值在XMM0中。少于64位的参数并没有做零扩展,此时高位充斥着垃圾。

假设一个function传入8个参数,从后往前传
foo(0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800);

1
2
3
4
5
6
7
8
9
push 0x800
push 0x700
mov r9d, 0x600
mov r8d, 0x500
mov ecx, 0x400
mov edx, 0x300
mov esi, 0x200
mov edi, 0x100
call foo

到第6个参数的时候才开始mov

Function Prologue
核心内容—理解function进栈和出栈的过程
维基百科
call 将下一个指令放在stack上面
400522: call 4004e7
400527: … —rip
(不知道400522多长,放在527上)

4004e7: push rbp 往上移
4004e8: mov rbp, rsp
4004eb: sub rsp, 0x10 开辟空间(offest)

400513: leave
400514: ret

leave – mov rsp, rbp
– pop rbp

Buffer Overflow 覆盖掉rip(return addresss)

CATALOG