iloveflag-blog

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
  1. 1. pwntools常用指令
  2. 2. 例1
  3. 3. ELF header
  4. 4. Function Prologue
  5. 5. Buffer Overflow 覆盖掉rip(return addresss)