天天看点

pwn学习笔记

PWN学习笔记——初稿

注明:本篇学习笔记是入门学习pwn时的随笔,所以不具有任何参考价值 ,仅作为对学习路线回顾参考的笔记以及入门纪念。

使用 Kali Linux , 称霸局域网 ![doge]

调试,调试!

Ida中的静态调试显示的函数和输出之间的距离,有时候会因为各种原因😁而显示错误,需要用pwndbg动态调试观察一下。淦,gdb显示的地址有时候也不对

IDA基本操作 (静态调试)

shift + F12

space

F5

ctrl + F

Pwndbg基本操作(动态调试)

Pwndbg + 文件名  进入对某个文件的调试

r 运行

b + 地址/函数  设置断点

checksec + 文件名  查看保护措施

stack + 数字  查看栈段

vmmap' 显示虚拟内存的的空间分布(观察读写的权 限是否有冲突-w与x不同时出现

plt 查看文件里的plt表项

x + 地址 显示该地址的内容和地址

got 查看got中保存的函数数量及其字节、数据等信息

disass + 地址 反汇编地址的数据,进而查看其汇编代码或plt

c 继续执行程序,直到遇到断点/程序中断

start 开始执行程序,会停到main函数;如果没有main函数,则会停到程 序的入口

s 附近

backtrace 显示函数调用栈段的状态

return 快速回到mian函数

求求了,用用py吧 🐶

(context.arch = “amd64”)  调整攻击环境 

shellcode.sh()

print(xxx)  更清楚地查看shellcode

print(asm(xxx))  查看shellcode的机器码

获取shellcode : 1.shellstore 2.pwntools – shellcraft.sh() (后面就是方法) 

Print(asm(shellcode.(amd64.)sh()))

嘿嘿嘿·🤭,脚本(介绍一下大致模板,最简单的那种啊,别误会)

vim exp.py

from pwn import *
​
(context.arch = "amd64")
​
io = process("本地文件路径")  //与本地文件交互 
​
OR  
​
io = remote("IP", 端口 )
​
io.recvline()               //接受程序给的文件
​
payload = b'”x”(字节型的数据) + p32(劫持程序的地址)  //将一个整数的地址转化成字节型的数据  32位的                                                   ebp占4个字节,64位的·ebp占8个字节
io.send(payload)            //发送数据   
​
OR  
​
io.sendline(payload)        //发送一行数据,相当于在数据末尾加/n;
​
io.interactive()            //交互       
from pwn import *
​
(context.arch = "amd64")
​
io = process("本地文件路径")   //与本地文件交互 
​
OR  
​
io = remote("IP", 端口 )
​
io.recvline()                //接受程序给的文件
​
asm(shellcode.(amd64.)sh())  //获取shellcode的机器码    
​
payload = asm( shellcode.(amd64.)sh()),lhust( 112, b’A ) /*补充字节流(这里就是A )到112 */ + p32( 劫持程序的地址(可以是全局变量的地址) )
​
io.send(payload)            //发送数据   
​
OR  
​
io.sendline(payload)        //发送一行数据,相当于在数据末尾加/n;
​
io.interactive()            //交互       

还有很多呐!

呐,shellcode注意啥啊

bss默认可执行,因此我们可以通过全局变量向其输入shellcode

gets 漏洞

未初始化的全局变量保存在bss里

不会算数,py来救

使用python计算栈段之间的距离

0x….(高地址) – 0x…(低地址)

>>>十进制数

Hex(十进制)

>>>十六进制

保护措施 🛡

1-NX 栈不可执行

2-ASLR 让函数的栈、共享连接库、堆段进行地址随机化,

0 – 未打开;1 – 部分随机化;2 – 全部随机化

关闭ASLR – “echo 0 > /proc/sys/kernel/randomize_va_space”

3-Canary(金丝雀) 在调用一个函数,刚创建栈帧时,首先把一个值(canary)放在低地址空间里,在销毁 函数时,先检查这个值(canary)是否发生改变,如果值改变,就会其强行将程序退出

4-Pie 编译时打开开关,随机化elf文件映像(text,bss。data)

程序进不去怎么办😱

修改文件权限

#!/bin/sh
​
gcc -fno-stack-protector -z execstack -no-pie -g -o re2stack ret2stack.c
​      

-fno-stack-protector 关闭canary,使栈溢出首先可行

-z execstack  打开栈的可执行权限

-no-pie  关闭pie

-g  带上调试信息,便于观看(一定要带着re2stack.c)

-o  输出文件名

请问字节是啥🤐

8比特 – 1 字节

每4比特可以直接写成一个16进制的值,

每两个16进制数就是1个字节

ROP!!!

没有连续的代码,但是通过一段一段的这个函数中包含的代码片段,达到相同的执行效果,即模拟程序的执行

其中思想的不同:没有一步到位的地址一次覆盖到tet,调用shell(即调用shell攻击目标,无法通过一个地址一次,所以需要,自己将程序中的指令组合起来,起到shell的作用)

我们所需要的为eaxebx…赋值的代码本来就存在,但是不连续,我们需要把他们组成一个链式结构(gadget),所以需要溢出很长的一段数据,把这些调成想要的格式,使其能够连续工作,并使其最后一条指令为ret。

对于系统调用,要在所有以ret结尾的代码中,找出个代码片段,它们的作用分别是pop eax、pop ebx、pop ecx、pop edx,pop一个寄存器的指令可以将数值直接写到栈上

PS:系统调用 —— 本质上只是一段函数,X86使用中断进行系统调用,第一个栈帧是main函数的栈帧,在main函数之前执行的所有函数都是没有栈帧的

pwn学习笔记

ret2syscall

因为需要执行大量代码段,故通过局部变量溢出, 组合一些gadget执行大量的代码片段,故将从ret开始的一大段栈空间,覆盖成gadget地址和对应的参数,此时,在main函数返回时,就会返回到已经被覆盖掉的,现在是ret的地址, 并执行指令

(ret把当前栈顶的值pop到eip)ret等效于pop eip

pwn学习笔记

pwn学习笔记
pwn学习笔记

get ­­­­­­­­­­­­­­­­­­­­--binary 文件名 -- only “ pop | ret 要寻找的指令|管道符 grep xx 把输入参数中含有xx的命令显示出来

Ret = pop xxx 即把xxx弹出到eip 

Xor 清空寄存器

下面是示例!

pwn学习笔记
pwn学习笔记

Int 0x80 ( eax = 0xb , ebx = …, ecx = 0,edx = 0 )进行系统调用( int – 中断指令 ),通过寄存器传参,来确定要调用哪一个函数。在执行int 0x80 这个汇编代码对应的机器码时,要确保四个寄存器都已经存储了对应的函数所需要的参数,即0xb这一个系统调用号对应的sys_execve() 对应的内核里的函数的调用号,而0xb 在这里·也带代表了那个函数

下面使用pwntools便捷获取/bin/sh的地址

pwn学习笔记

使用next传入生成器

pwn学习笔记

最后一层是要输入的垃圾数据,倒数第三行是要给

倒数第二层输入的数据,以此类推

pwn学习笔记

动态链接 

当我们使用file命令去查看一些文件的属性时,下面两点也会被显示出来:

动态链接:gcc -fno-pie -o dytest xxx.py   dynamically link

静态链接:gcc -fno-poe --static -o statest xxx.py   statically link

本块主要讨论动态链接

动态链接相关结构

pwn学习笔记

dynamic section 为操作系统描述了整个动态链接的完整内容

提供动态链接相关信息

link_map 保存进程载入的动态链接库的链表

dl_runtime_resolve 解析第一次在动态链接的函数的真实地址

装载器中用于解析动态链接库中函数的实际地址的函数

got  全局的符号、变量地址

got.plt 全局的函数地址

动态占用内存小(其库函数占用少)

动态链接过程

ldd 文件名 查看文件用到的所有动态链接库

pwn学习笔记

下面分流程分析

pwn学习笔记

text —— 代码节;foo@olt —— foo是自己写的函数;plt是代码段中存放函数真实地址的一个节; PLT0(PLT最开始的两段指令)

因为foo是个动态链接库中的代码,所以call foo,并不能直接跳转到它自己代码段里的foo函数,只能去代码段中的plt节,而每个被调用的动态链接库中的函数都会在其中创立一个表项,

1、call foo@plt 进程首次调用 foo

2、jmp *(foo@GOT) 跳转到 .plt 中的 foo 表项,plt 中的代码立即跳转到.got.plt 中记录的地址

3、push 由于进程是第一次调用 foo,故.got.plt 中记录的地址是 foo@plt+1

4、jmp 回到 .plt 是,解析 foo 的实际地址

5、push *(GOT+4) 跳转到 .plt 头部,为 dl_runtime_resolve 函数传参

6、push *(GOT+4) 跳转到 .plt 头部,为 dl_runtime_resolve 函数传参

pwn学习笔记

7、call_fix_up dl_runtime_resolve 函数解析 foo 的真正地址填入 .got.plt 中

8、ret 0xc 此后 .got.plt 中保存的是 foo 的真实地址

pwn学习笔记

9、call foo@plt 系统第二次调用foo

10、jum *(foo@GOT)  直接自 .got.plt 跳转到 foo 的真实地址,没有了第一次的解析地址过程

ok,接下来展示完整流程

pwn学习笔记

IDA的细节

init 用作初始化的一个节,记录了初始化代码

plt 存放函数真实地址的一个节

got 存放数据的节

ret2libc

往往依赖于rop所需要的各种gadget创造执行shellcode的环境,但其目标是返回libc里的system函数这一类可以为我们提供一个shell的函数

TRANSLATE with

x

English

Arabic Hebrew Polish
Bulgarian Hindi Portuguese
Catalan Hmong Daw Romanian
Chinese Simplified Hungarian Russian
Chinese Traditional Indonesian Slovak
Czech Italian Slovenian
Danish Japanese Spanish
Dutch Klingon Swedish
English Korean Thai
Estonian Latvian Turkish
Finnish Lithuanian Ukrainian
French Malay Urdu
German Maltese Vietnamese
Greek Norwegian Welsh
Haitian Creole Persian

COPY THE URL BELOW

Back

EMBED THE SNIPPET BELOW IN YOUR SITE

Enable collaborative features and customize widget: Bing Webmaster Portal