[刺客伍六七&黑客] 魔刀千刃evilblade的使用手册与开源
0x00 前言
2023.8.15 夜里
非常欢迎使用我的魔刀千刃,并且欢迎各位师傅对我的开源代码进行指导!
—–Offense without defense,
unparalleled in the world.—–
Welcome to the universe of N1nEmAn.
To find detailed usage instructions for evilblade,
please visit cnblogs.com/9man.
访问连接:https://pypi.org/project/evilblade/
0x01 安装
安装直接如下命令。
pip3 install evilblade
本包还依赖包LibcSearcher和pwntools,如未安装,请安装。
pip3 install pwntools
pip3 install LibcSearcher
0x02 内置帮助
为了兼容问题内置帮助我没有写中文,在这里写中文版本的。
内置帮助命令:python -m pydoc evilblade
,按q
退出。
0x03 中文帮助
dp(name, data)
# 数据打印
dpx(name, data)
# 数据以十六进制格式打印
evgdb(*argv)
# 设置 gdb,也称为 evil-gdb
# 如果需要设置断点,请将 'b address/defname' 作为参数。
fmt(offset, begin, end, size, written)
# 用于格式化字符串漏洞,但实用性不高。
getbase(add, defname, *args)
# 计算 libc 的基地址。"add" 是泄露的地址,"defname" 是库函数名,"*args" 是需要减去的额外偏移量。
getd(i, j)
# 用于十进制格式
# 类似于 getx32
getx(i, j)
# 用于十六进制格式
# 类似于 getx32
getx32(i, j)
# 用于 32 位
# 在使用 tet() 测试过的 '\xff' 格式之后,你可以接收地址。
# "i" 参数表示接收数据的开头,"j" 表示结尾。
# 通常 "i" 设置为 0,"j" 设置为 -1。
# 不断修改 "i" 和 "j" 的值,直到获得满意的结果为止。
getx64(i, j)
# 用于 64 位
# 类似于 getx32
gotadd(defname, *args)
# 没有 PIE 保护,如果参数只有 "defname",得到 GOT 表地址。
# 有 PIE 保护,如果参数只有 "defname",得到 GOT 表地址偏移。加上第二个参数作为基地址,得到实际 GOT 表地址。
ia lambda (...)
# 启动交互式 shell
libset(libc_val)
# 设置你的 libc,也称为 libc-set
n2b lambda x
# 将数字转换为字节
pltadd(defname, *args)
# 类似于 gotadd,但获取的是 PLT 表的地址
rgetbase(add, defname, *args)
# 类似于 'getbase',但用于远程 libc 库
rl lambda (...)
# 接收一行数据,相当于 p.recvline()
rlibset(defname, add)
# 设置远程 libc 库。
rop lambda r
# 将值列表转换为 ROP 链(64 位)
rsetup(mip, mport)
# 建立远程连接
rsymoff(defname, *args)
# 类似于 'symoff',但用于远程 libc 库
ru lambda s
# 接收数据,直到特定字符串,相当于 p.recvuntil(s)
rv lambda x
# 接收数据,相当于 p.recv(x)
sa lambda t, s
# 在特定字符串后发送数据,相当于 p.sendafter(t, s)
sd lambda s
# 发送数据,相当于 p.send(s)
setup(p_val)
# 设置你的进程和 ELF
sl lambda s
# 发送带有 '\n' 的数据,相当于 p.sendline(s)
sla lambda t, s
# 在特定字符串后发送一行数据,相当于 p.sendlineafter(t, s)
sn lambda n
# 发送一个带有 '\n' 的数字,相当于 sl(n2b(n))
sna lambda t, n
# 在特定字符串后发送一个数字,相当于 sla(t, n2b(n))
symadd(defname, *args)
# 类似于 gotadd,但获取的是 SYM 表的地址
symoff(defname, *args)
# 如果参数只有 'defname',你会得到偏移量。
# 如果有第二个参数作为基地址,你会得到函数的实际地址。
terset(get)
# 如果你不能直接运行 GDB,请根据情况使用 'terset' 来设置终端。使用 'echo $TERM' 的输出作为参数。
tet()
# 接收一行数据,并将其显示给你
uu64 lambda data
# 从字节中解包一个 64 位无符号整数
0x02 开源代码
from pwn import *
from LibcSearcher import *
'''
明知道是陷阱,
为什么还要来。
'''
# Convert a number to bytes
n2b = lambda x: str(x).encode()
# Receive data, equivalent to p.recv(x)
rv = lambda x: p.recv(x)
# Receive a line of data, equivalent to p.recvline()
rl = lambda: p.recvline()
# Receive data until a specific string, equivalent to p.recvuntil(s)
ru = lambda s: p.recvuntil(s)
# Send data, equivalent to p.send(s)
sd = lambda s: p.send(s)
# Send data with '\n', equivalent to p.sendline(s)
sl = lambda s: p.sendline(s)
# Send a number with '\n', equivalent to sl(n2b(n))
sn = lambda n: sl(n2b(n))
# Send data after a specific string, equivalent to p.sendafter(t, s)
sa = lambda t, s: p.sendafter(t, s)
# Send a line of data after a specific string, equivalent to p.sendlineafter(t, s)
sla = lambda t, s: p.sendlineafter(t, s)
# Send a number after a specific string, equivalent to sla(t,n2b(n))
sna = lambda t, n: sla(t, n2b(n))
# Start an interactive shell
ia = lambda: p.interactive()
# Convert a list of values to a ROP chain (64-bit)
rop = lambda r: flat([p64(x) for x in r])
# Unpack a 64-bit unsigned integer from bytes
uu64 = lambda data: u64(data.ljust(8, b'\x00'))
##Set your libc, aka libc-set
def libset(libc_val):
global libc
libc = ELF(libc_val)
#Set your prosecc and ELF
def setup(p_val):
global p
global elf
p = process(p_val)
elf = ELF(p_val)
#Establish remote connection
def rsetup(mip, mport):#设置远程连接 remote setup
if args.P:
global p
p = remote(mip,mport)
##Recieve a line of data, and show it for you
def tet():
#test,测试接收数据
p = globals()['p']
r = ru('\n')
print('\n----------------\n','add','is >>> ',r,'\n---------------')
return r
#For 64-bit
#Just like getx32
def getx64(i,j):
if i != 0:
r = (ru('\n'))[i:j]
dp('getx64',r)
r = u64(r.ljust(8,b'\0'))
print('\n----------------\n','add','is >>> ',hex(r),'\n---------------')
return r
else:
r = (ru('\n'))[:j]
dp('getx64',r)
r = u64(r.ljust(8,b'\0'))
print('\n----------------\n','add','is >>> ',hex(r),'\n---------------')
return r
#For 32-bit
#After testing with tet(), addresses can be received for the '\xff' format.
#The 'i' parameter represents the start of the received data, while 'j' indicates the end.
#Usually, 'i' is set to 0, and 'j' is set to -1.
#Continuously adjust the values of 'i' and 'j' until you obtain the desired result.
def getx32(i,j):
if i != 0:
r = (ru('\n'))[i:j]
dp('getx32',r)
r = u32(r.ljust(4,b'\0'))
print('\n----------------\n','add','is >>> ',hex(r),'\n---------------')
return r
else:
r = (ru('\n'))[:j]
dp('getx32',r)
r = u32(r.ljust(4,b'\0'))
print('\n----------------\n','add','is >>> ',hex(r),'\n---------------')
return r
#For the hex format
#Just like getx32
def getx(i,j):
if i != 0:
r = (ru('\n'))[i:j]
dp('geti',r)
r = int(r,16)
print('\n----------------\n','add','is >>> ',hex(r),'\n---------------')
return r
else:
r = (ru('\n'))[:j]
dp('geti',r)
r = int(r,16)
print('\n----------------\n','add','is >>> ',hex(r),'\n---------------')
return r
#For the decimal format
#Just like getx32
def getd(i,j):
if i != 0:
r = (ru('\n'))[i:j]
dp('geti',r)
r = int(r,10)
print('\n----------------\n','add','is >>> ',hex(r),'\n---------------')
return r
else:
r = (ru('\n'))[:j]
dp('geti',r)
r = int(r,10)
print('\n----------------\n','add','is >>> ',hex(r),'\n---------------')
return r
'''
只攻不防,
天下无双—————
魔刀千刃。
'''
##计算世界
#Calculate the base address of libc. "add" is the leaked address, "defname" is the library function name, and "*args" are the excess offsets that need to be subtracted.
def getbase(add,defname,*args):
#计算libcbase,args作为多余参数相减 get libcbase
base = add - libc.sym[defname]
for num in args:
base -= num
print('\nloading...')
print('\n----------------\nget!your base is >>> ',hex(base),'\n--------------')
return base
ter = 'NULL'
#If you are unable to directly run GDB, please use the 'terset' to set the terminal according to your situation. Use the output of 'echo $TERM' as the parameter.
def terset(get):
global ter
dp('ter',ter)
#Set gdb,aka evil-gdb
#If you need to set a breakpoint, please use 'b address/defname' as the parameter.
def evgdb(*argv):
p = globals()['p']
ter = globals()['ter']
#获取全局变量值
dp('gdbter',ter)
if ter!='NULL':
context.terminal = [ter, '-e']
if args.G:
if(len(argv)==0):
gdb.attach(p)
else:
gdb.attach(p,argv[0])
#If the parameter is only 'defname', you will get the offset.
#If there's a second parameter as the base address, you will get the actual address of the function.
def symoff(defname,*args):#计算或者设置偏移symbol's offset
if(len(args)>0):
ba = args[0]
print('\n----------------\nyour ',defname,'offset is >>> ',hex(libc.sym[defname]),'\n---------------')
print('\n----------------\nyour ',defname,'is in >>> ',hex(ba+libc.sym[defname]),'\n---------------')
return libc.sym[defname]+ba
else:
print('\n---------------\nyour ',defname,'offset is >>> ',hex(libc.sym[defname]),'\n---------------')
return libc.sym[defname]
#Without PIE, if only "defname", obtain the address of the GOT table.
#With PIE, if only "defname", obtain the offset of the GOT table. Adding the second parameter as the base address will give you the actual GOT table address.
def gotadd(defname,*args):#获取got表地址got'sadd
if (len(args) > 0):
return elf.got[defname]+args[0]#有pie的时候
return elf.got[defname]
#Jusr like gotadd,but obtain the address of the PLT table
def pltadd(defname,*args):#获取got表地址got'sadd
if (len(args) > 0):
return elf.plt[defname]+args[0]#有pie的时候
return elf.plt[defname]
#Just like gotadd,but obtain the address of the SYM table
def symadd(defname,*args):#获取got表地址got'sadd
if (len(args) > 0):
return elf.sym[defname]+args[0]#有pie的时候
return elf.sym[defname]
#Data print
def dp(name,data):#打印数值data print
print('\n---------------\nyour ',name,' is >>> ',(data),'\n---------------')
#Data print as hex
def dpx(name,data):#hex打印数值data print
print('\n---------------\nyour ',name,' is >>> ',hex(data),'\n---------------')
'''
因为,
我有想要保护的人。
'''
##查库世界
#Set the remote libc library.
def rlibset(defname,add):
#远程libc设置
global rlibc
rlibc = LibcSearcher(defname, add)
#Just like 'getbase', but for remote libc library
def rgetbase(add,defname,*args):
#计算远程libcbase,args作为多余参数相减 get libcbase
base = add - rlibc.dump(defname)
for num in args:
base -= num
print('\nloading...')
print('\n----------------\nget!your base is >>> ',hex(base),'\n--------------')
return base
#Just like 'symoff',but for remote libc library
def rsymoff(defname,*args):#计算或者设置偏移symblol's offset
if(len(args)>0):
ba = args[0]
print('\n----------------\nyour ',defname,'offset is >>> ',hex(rlibc.dump(defname)),'\n---------------')
print('\n----------------\nyour ',defname,'is in >>> ',hex(ba+rlibc.dump(defname)),'\n---------------')
return rlibc.dump(defname)+ba
else:
print('\n---------------\nyour ',defname,'offset is >>> ',hex(rlibc.dump(defname)),'\n---------------')
return rlibc.dump(defname)
#攻击世界
#For fmt, but the reliability is not high.
def fmt(offset,begin,end,size,written):
#fmt利用
payload = fmtstr_payload(offset,{begin: end},write_size = size,numbwritten=written)
return payload
'''
offset(int) - 您控制的第一个格式化程序的偏移量
字典(dict) - 被写入地址对应->写入的数据,可多个对应{addr: value, addr2: value2}
numbwritten(int) - printf函数已写入的字节数
write_size(str) - 必须是byte,short或int。告诉您是否要逐字节写入,短按short或int(hhn,hn或n)
'''