Pwn Note

install tools

yay -S yay -S blackarch/rz-cutter
yay -S aur/rz-jsdec-git
yay -S blackarch/rz-ghidra =>optional

汇编基础

x86 处理器有 8 个 32 位通用寄存器 image-20230605233029900

汇编指令 Instructions

机器指令通常分为 3 类:数据移动指令, 逻辑运算指令和流程控制指令。

<reg32 任意的 32 位寄存器 (%eax, %ebx, %ecx, %edx, %esi, %edi, %esp 或者 %eb)
<reg16 任意的 16 位寄存器 (%ax, %bx, %cx 或者 %dx)
<reg8 任意的 8 位寄存器 (%ah, %al, %bh, %bl, %ch, %cl, %dh, %dl)
<reg 任意的寄存器
<mem 一个内存地址, 例如 (%eax), 4+var, (%eax, %ebx, 1)
<con32 32 位常数
<con16 16 位常数
<con8 8 位常数
<con 任意 32位, 16 位或者 8 位常数

数据移动指令

mov 移动

mov 指令将数据从它的第一个参数 (即寄存器中的内容, 内存单元中的内容, 或者一个常数值)复制到它的第二个参数 (即寄存器或者内存单元) 语法

mov <reg, <reg
mov <reg, <mem
mov <mem, <reg
mov <con, <reg
mov <con, <mem

例子

mov %ebx, %eax ;将 EBX 中的值复制到 EAX 中
mov $5, var(,1) ;将数字 5 存到字节型内存单元 "var"

image-20230605234100281

push 入栈

push 指令将它的参数移动到硬件支持的栈内存顶端 语法

push <reg32
push <mem
push <con32

例子

push %eax ;将 EAX 送入栈
push var(,1) ;将 var 对应的 4 字节大小的数据送入栈中

pop 出栈

pop 指令从硬件支持的栈内存顶端移除4 字节的数据, 并把这个数据放到该指令指定的参数中 ( 即寄存器或者内存单元 )。 语法

pop <reg32
pop <mem

例子

pop %edi ;将栈顶的元素移除, 并放入到寄存器 EDI 中.
pop (%ebx) ;将栈顶的元素移除, 并放入从 EBX 开始的 4 个字节大小的内存单元中.

lea 加载有效地址

lea 指令将其第一个参数指定的内存单元 放入到 第二个参数指定的寄存器中。 汇编语言中 lea 指令和 mov 指令的区别 ? MOV 指令的功能是传送数据,例如 MOV AX,[1000H] ,作用是将 1000H 作 为偏移地址,寻址找到内存单元,将该内存单元中的数据送至 AX; LEA 指令的功能是取偏移地 址,例如 LEA AX,[1000H] ,作用是将源操作数 [1000H] 的偏移地址 1000H 送至 AX。 语法

lea <mem, <reg32

例子

lea (%ebx,%esi,8), %edi ;EBX+8*ESI 的值被移入到了 EDI
lea val(,1), %eax ;val 的值被移入到了 EAX

逻辑运算指令

add 整数相加

#语法
add <reg, <reg
add <mem, <reg
add <reg, <mem
add <con, <reg
add <con, <mem
#例子
add $10, %eax ;EAX 中的值被设置为了 EAX+10.
addb $10, (%eax) ;往 EAX 中的值 所代表的内存单元地址 加上 1 个字节的数字 10.

sub 整数相减

#语法
sub <reg, <reg
sub <mem, <reg
sub <con, <reg
sub <con, <mem
sub %ah, %al ;AL 被设置成 AL-AH
sub $216, %eax ;将 EAX 中的值减去 216

inc 指令让它的参数加 1, dec 指令则是让它的参数减去 1

#语法
inc <reg
inc <mem
dec <reg
dec <mem
#例子
dec %eax ;EAX 中的值减去 1
incl var(,1) ;将 var 所代表的 32 位整数加上 1.

imul 整数相乘

#语法
imul <reg32, <reg32
imul <mem, <reg32
imul <con, <reg32, <reg32
imul <con, <mem, <reg32
#例子
imul (%ebx), %eax ;将 EAX 中的 32 位整数, 与 EBX 中的内容所指的内存单元, 相乘, 然后把结果存到 EAX 中.
imul $25, %edi, %esi ;ESI 被设置为 EDI * 25.

Linux ELF

image-20230606000212872 demo code

#include<stdio.h>
int global_init_var = 10;
int global_uninit_var;
void func(int sum) {
printf("%d\n", sum);
}
void main(void) {
static int local_static_init_var = 20;
static int local_static_uninit_var;
int local_init_val = 30;
int local_uninit_var;
func(global_init_var + local_init_val + local_static_init_var);
}
gcc -m32 -c elf_demo.c -o elfDemo.o   #LSB relocatable  可重定位文件
gcc -m32 elf_demo.c -o elfDemo.out    #  LSB pie executable,dynamically linked
gcc -m32 -static elf_demo.c -o elfDemo_Static.out  #LSB executable,statically linked
file -L /usr/lib32/libc.so.6  #LSB shared object,dynamically linked

ldd 命令打印所依赖的共享库

ldd elfDemo.out
ldd elfDemo_static.out

读符号表

readelf -s  elfDemo.o

hexdump .shstrtab字段

readelf -x .shstrtab  elfDemo.o

gdb 调试

gdb
file elfDemo.o
disassemble main
0x565561bb <+0>:     lea    ecx,[esp+0x4]  #把[esp+0x4]的地址传给ecx
0x565561bf <+4>:     and    esp,0xfffffff0
0x565561c2 <+7>:     push   DWORD PTR [ecx-0x4]
0x565561c5 <+10>:    push   ebp
0x565561c6 <+11>:    mov    ebp,esp
0x565561c8 <+13>:    push   ecx
0x565561c9 <+14>:    sub    esp,0x14
0x565561cc <+17>:    call   0x56556205 <__x86.get_pc_thunk.ax>
0x565561d1 <+22>:    add    eax,0x2e23
0x565561d6 <+27>:    mov    DWORD PTR [ebp-0xc],0x1e
0x565561dd <+34>:    mov    ecx,DWORD PTR [eax+0x1c]
0x565561e3 <+40>:    mov    edx,DWORD PTR [ebp-0xc]
0x565561e6 <+43>:    add    edx,ecx
0x565561e8 <+45>:    mov    eax,DWORD PTR [eax+0x20]
0x565561ee <+51>:    add    eax,edx
0x565561f0 <+53>:    sub    esp,0xc
0x565561f3 <+56>:    push   eax
0x565561f4 <+57>:    call   0x5655618d <func>
0x565561f9 <+62>:    add    esp,0x10
0x565561fc <+65>:    nop
0x565561fd <+66>:    mov    ecx,DWORD PTR [ebp-0x4]
0x56556200 <+69>:    leave
0x56556201 <+70>:    lea    esp,[ecx-0x4]
0x56556204 <+73>:    ret