[shellcode学习] 绕过条件判断

shellcode学习第一个例子。

以下有一段c语言编写的命令行程序,检验用户输入的数字,并判断是否合法。这里用户的输入被放在了函数的缓冲区里,但程序没有对缓冲区长度做检查,留下了漏洞。这里可以利用该漏洞绕过数字检察,使得任意输入都会被判定为正确。

validate_serial 中,do_valid_stuff 的地址溢出到函数的返回值上,就可实现。

源程序

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

int valid_serial(char * psz)
{
    size_t len = strlen(psz);
    unsigned total = 0;
    size_t i;

    if (len<10)
        return 0;

    for (i = 0; i < len; i++)
    {
        if ((psz[i]<‘0‘) || (psz[i]>‘z‘))
            return 0;
        total += psz[i];
    }

    if (total % 853 == 83)
        return 1;

    return 0;
}

int valildate_serial()
{
    char serial[24];

    fscanf(stdin, "%s", serial);

    if (valid_serial(serial))
        return 1;
    else
        return 0;
}

int do_valid_stuff()
{
    printf("the serial number is valid!\n");
    exit(0);
}

int do_invalid_stuff()
{
    printf("invalid serial number!\nexiting\n");
    exit(1);
}

int main(int argc, char * argv[])
{
    if (valildate_serial())
        do_valid_stuff();
    else
        do_invalid_stuff();

    return 0;
}

反汇编main

(gdb) disass main
Dump of assembler code for function main:
   0x0804861a <+0>:     push   %ebp
   0x0804861b <+1>:     mov    %esp,%ebp
   0x0804861d <+3>:     call   0x804859f <valildate_serial>
   0x08048622 <+8>:     test   %eax,%eax
   0x08048624 <+10>:    je     0x804862d <main+19>
   0x08048626 <+12>:    call   0x80485de <do_valid_stuff>
   0x0804862b <+17>:    jmp    0x8048632 <main+24>
   0x0804862d <+19>:    call   0x80485fc <do_invalid_stuff>
   0x08048632 <+24>:    mov    $0x0,%eax
   0x08048637 <+29>:    pop    %ebp
   0x08048638 <+30>:    ret
End of assembler dump.

可得到 do_valid_stuff 的地址为 0x08048626。validate_serial 的返回地址为 0x08048622。下面就通过溢出修改返回地址。

缓冲区溢出

源码中,缓冲区长度为24,理论上只要覆盖24+2处的数据就可以了。我们需要检验一下,在fscanf处打断点,观察堆栈内容。

Breakpoint 1, valildate_serial () at serial.c:31
31          fscanf(stdin, "%s", serial);
(gdb) x/20x $esp
0xbffff6bc:     0x0804869b      0x00000001      0xbffff794      0xbffff79c
0xbffff6cc:     0xbffff6e8      0xb7e987f5      0xb7ff0590      0x0804865b
0xbffff6dc:     0xb7fc7ff4      0xbffff6e8      0x08048622      0xbffff768
0xbffff6ec:     0xb7e7fe46      0x00000001      0xbffff794      0xbffff79c
0xbffff6fc:     0xb7fe0860      0xb7ff6821      0xffffffff      0xb7ffeff4
(gdb)c
AAAAAAAAAABBBBBBBBBBCCCCCCCC1234

Breakpoint 2, valildate_serial () at serial.c:33
33          if (valid_serial(serial))
(gdb) x/20x $esp
0xbffff6bc:     0xb7fc8440      0x080486d0      0xbffff6c8      0x41414141
0xbffff6cc:     0x41414141      0x42424141      0x42424242      0x42424242
0xbffff6dc:     0x43434343      0x43434343      0x34333231      0xbffff700
0xbffff6ec:     0xb7e7fe46      0x00000001      0xbffff794      0xbffff79c
0xbffff6fc:     0xb7fe0860      0xb7ff6821      0xffffffff      0xb7ffeff4
(gdb)

可以看到“1234”对应的ascii码“0x34333231”已经被写入了返回值”0x08048622”原来所在的地方。

接下来把“1234”换成我们需要的返回地址。

我们回到shell中实验一下

[email protected]:~/Desktop/shellcode/validate_serial$ printf "AAAAAAAAAABBBBBBBBBBCCCCCCCC\x26\x86\x04\x08" | ./serial
the serial number is valid!

成功绕过了程序的检验机制。

时间: 2024-10-09 09:00:52

[shellcode学习] 绕过条件判断的相关文章

C学习if条件判断和for循环

通过学习if条件判断和for循环之后,做了一个实例.实现的实例都在代码中有详细的注释. #include <stdio.h> /****************************************************** * 输入一个数字n,求 * 1+1+2+1+2+3+1+2+3+4...+n * 该实例主要为了练习if语句和for语句 ******************************************************/ int main(void

Shell学习笔记 - 条件判断式

1. 判断格式 1) test 参数 文件 例: test -e /root/install.log 2) [ 参数 文件 ]  -- 推荐使用 例: [ -e /root/install.log ] 注意:中括号后面和前面需要有空格 2. 判断文件类型参数 1)-d 文件:判断该文件是否存在,并且是否为目录文件 2)-e 文件:判断文件是否存在 3)-f 文件:判断文件是否存在,并且是否为普通文件 4)-s 文件:判断文件是否存在,并且是否为非空 5)其他文件类型判断: -b 块设备文件:-c

Java学习之==&gt;条件判断、循环控制

一.条件判断 1.if-else 示例: /** * 第1种,1个分支 */ public void case1() { int age = 15; if (age > 18) { System.out.println("成年人"); } } /** * 第2种,2个分支 */ public void case2() { int age = 15; if (age > 18) { System.out.println("成年人"); } else { S

shell学习之条件判断test

1.按照『文件类型』进行判断(存在与否) -e:该『文件』是否存在?存在为真(常用)-f:该『文件』是否为普通文件(file)?(常用)-d:该『文件』是否为目录文件(directory)?(常用)-b:该『文件』是否为一个块设备文件(block devic)?装置-c:该『文件』是否为一个字符设备文件(character device)?装置 -s:改『文件』是否为非空?-S:该『文件』是否为一个套接字文件(Socket)?文件-p:该『文件』是否为一个管道文件 FIFO (pipe) ?文件

Sass学习笔记 -- 初步了解函数、运算、条件判断及循环

函数 sass定义了很多函数可供使用,当然你也可以自己定义函数,以@fuction开始.sass的官方函数链接为:sass fuction,实际项目中我们使用最多的应该是颜色函数,而颜色函数中又以lighten减淡和darken加深为最,其调用方法为lighten($color,$amount)和darken($color,$amount),它们的第一个参数都是颜色值,第二个参数都是百分比. //scss $baseFontSize:      10px !default; $gray:    

SHELL学习笔记----IF条件判断,判断条件

SHELL学习笔记----IF条件判断,判断条件 前言: 无论什么编程语言都离不开条件判断.SHELL也不例外.  if list then           do something here       elif list then           do another thing here       else          do something else here fi  EX1: #!/bin/bash if [ `uname -m` == "x86_64" ]

Linux下Python学习笔记 2:条件判断、循环

一.条件判断 if 语句 比如,输入用户年龄,根据年龄打印不同的内容,在Python程序中,可以用if语句实现: 注意: Python代码的缩进规则.具有相同缩进的代码被视为代码块,上面的3行 print 语句就构成一个代码块(但不包括第4行的print).如果 if 语句判断为 True,就会执行这个代码块. 缩进请严格按照Python的习惯写法:4个空格,不要使用Tab,更不要混合Tab和空格,否则很容易造成因为缩进引起的语法错误. 在ubuntu下的vim中需要设置tab默认为4个空格,可

15、自学——Linux的学习进度与任务【bash编程之条件判断】

bash编程之条件判断 bash编程之条件判断:判定后续操作的前提条件是否满足 1.条件判断的常用判断类型(bash内生的): 整数测试 字符测试 文件测试   2.echo $?(执行状态返回值): 0:正确 1-255:错误 布尔值: 真 假 3.逻辑运算: 与运算: 真 && 真 = 真(0) 真 && 假 = 假(非0) 假 && 真 = 假 假 && 假 = 假 或运算: 真 || 真 = 真(0) 真 || 假 = 真 假 ||

Linux学习笔记--bash脚本编程之二、条件判断

 bash脚本编程之二.条件判断 条件判断: 如果用户不存在 添加用户,给密码并显示添加成功: 否则 显示用户已存在,没有添加 bash中如何实现条件判断? 整数测试 字符测试 文件测试 条件测试的表达式:     [expression]     [[expression]]     test expression 整数比较: -eq:测试两个整数是否相等:比如 $A -eq $B     -ne:测试两个整数是否不等:不等,为真:相等,为假:     -qt:测试一个数是否大于另一个数:大于