PWN 入门

星盟安全的 PWN 学习

基础

ELF

ELF 是 linux 下的可执行文件,一个 C 语言源文件变为 ELF 文件会经历以下步骤

  1. 编译(compile),从 C 源文件(a.c b.c),变为汇编语言文件(a.s b.s)
  2. 汇编(assembly),从汇编语言文件变为目标文件(a.o b.o,内容为机器码)
  3. 链接(link),将多个目标文件与库文件链接成为一个可执行文件(ELF 文件)

链接库文件也是 ELF 文件,动态链接库后缀为 .so,静态链接库为 .a

ELF 结构图

image-20210504213152816

程序装载和虚拟内存

段(segment)指程序在内存中的情况,节(section)则指程序在磁盘中的情况。一个段可能包含多个节,划分依据是 rwx 权限。

例如:

  • 代码段(text segment)包含代码(RX)与只读数据(R),包括 .text、.rodata、.hash、.dynsym、.dynstr、.plt、.rel.got 节
  • 数据段(data segment)包含可读写数据(RW),包括.data、.dynamic、.got、.got.plt、.bss 节
  • 栈段(Stack segment)

image-20210504214009872

每个进程有一个完整的进程空间(虚拟内存),共 4GB。其中低 3GB 为用户空间,高 1GB 为所有进程共享的内核空间。

虚拟内存的 mmap 段中的动态链接库仅在物理内存中装载一份。

虚拟地址空间(以64位为例)

image-20210504215104349

C 语言程序在内存中的组织

image-20210504220145552

大端序与小端序(通常是小端序)

image-20210504220543331

寄存器结构

image-20210504221921497

程序执行过程

image-20210504222101376

image-20210504222119360

汇编

常用汇编指令:MOV、LEA、ADD、SUB、PUSH、POP、CMP、JMP、J[condition]、CALL、LEAVE、RET。

溢出的概念:有符号数中,正数加正数只能是正数,负数加负数只能是负数,如果结果不对,就是产生了溢出

Shellcode

pwn 中,shellcode 指可以启用 shell 进行交互的代码。

execve syscall,在x86 中汇编代码是 int 0x80,x64 中是 int 0x3b,Linux Syscall 调用表,根据调用表,需要执行以下步骤能够 getshell

  1. 设置 ebx 指向字符串 “/bin/sh”
  2. 设置 exc=0,edx=0
  3. 设置 eax=0xb
  4. int 0x80 触发中断

x86 shellcode 汇编代码:

1
2
3
4
5
6
7
8
9
10
11
12
;;nasm -f elf32 i386.asm
;;ld -m elf_i386 -o i386 i386.o
;;objdump -d i386
global _start
_start:
push "/sh"
push "/bin"
mov ebx, esp ;; ebx="/bin/sh"
xor edx, edx ;; edx=0
xor ecx, ecx ;; ecx=0
mov al, 0xb ;; al=0xb
int 0x80

x64 shellcode 汇编代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
;;nasm -f elf64 x64.asm
;;ld-m elf_x86_64 -o x64 x64.o
;;objdump -d x64
global _start
_start:
mov rbx,'/bin/sh'
push rbx
push rsp
pop rdi
xor esi, esi
xor edx, edx
push 0x3b
pop rax
syscall

使用 pwntools 生成 shellcode

1
2
3
4
5
6
from pwn import *
# 32
context(log_level = 'debug', arch ='i386', os = 'linux')
# 64
# context(log_level = 'debug', arch ='amd6', os = 'linux')
shellcode = asm(shellcraft.sh())
作者

lll

发布于

2021-05-04

更新于

2022-09-19

许可协议