ShellCode是一种漏洞代码,中文名也叫填充数据,一般是用C语言或者汇编编写。在研究的过程中,自己也学到了一些东西,发现其中也有许多坑,所以贴出来,如果大家有碰到的,可以参考一下。

以启动电脑上的计算器为例,编写ShellCode其实就是两部分,一是获取ShellCode字节码,二是调用它。

获取方式一般是观察代码反汇编和内存相结合:

VOID Test()
{
HMODULE v1 = LoadLibraryA("kernel32.dll");//0X7778ff70
//WinExec("calc.exe", SW_SHOW); /*
00E31E5E mov esi,esp
00E31E60 push 0E36B30h
00E31E65 call dword ptr ds:[0E3A060h]
00E31E6B cmp esi,esp
00E31E6D call __RTC_CheckEsp (0E3111Dh)
00E31E72 mov dword ptr [v1],ea,0x
WinExec("calc.e,0xe", SW_SHOW); 00E31E75 mov esi,esp
00E31E77 push 5
00E31E79 push 0E36B40h
00E31E7E call dword ptr ds:[0E3A064h]
00E31E84 cmp esi,esp
00E31E86 call __RTC_CheckEsp (0E3111Dh) return 0;
*/
__asm
{ push ebp;
mov ebp, esp;
xor eax, eax;
push eax;
sub esp, 08h;
mov byte ptr[ebp - 0Ch], 63h; //c
mov byte ptr[ebp - 0Bh], 61h; //a
mov byte ptr[ebp - 0Ah], 6Ch; //l
mov byte ptr[ebp - 09h], 63h; //c
mov byte ptr[ebp - 08h], 2Eh; //.
mov byte ptr[ebp - 07h], 65h; //e
mov byte ptr[ebp - 06h], 78h; //x
mov byte ptr[ebp - 05h], 65h; //e lea eax, [ebp - 0ch];
push eax; //将calc.exe压入栈内 mov eax, 0x7778ff70;
call eax; //调用WinExec mov esp, ebp;
pop ebp;
} }

然后就是所谓的苦力活,将反汇编中的字节码一个一个抄出来,整合成为一个ShellCode

CHAR ShellCode[] = {
0x55,0x8B,0xEC,0x51,0x51,0x83,0x65,0xFC,0x00,0x56,0x57,0xC7,0x45,0xF8,0x63,0x61,
0x6C,0x63,0x64,0xA1,0x18,0x00,0x00,0x00,0x33,0xC9,0x8B,0x40,0x30,0x8B,0x40,0x0C,
0x8B,0x78,0x1C,0x8B,0x3F,0x8B,0x47,0x20,0x66,0x83,0x78,0x10,0x2E,0x74,0x06,0x41,
0x83,0xF9,0x02,0x7C,0xEE,0x8B,0x4F,0x08,0xBA,0xB9,0x6B,0xFF,0xCB,0xE8,0x23,0x00,
0x00,0x00,0x8B,0x4F,0x08,0xBA,0x13,0xB9,0xE6,0x25,0x8B,0xF0,0xE8,0x14,0x00,0x00,
0x00,0x6A,0x01,0x8D,0x4D,0xF8,0x51,0xFF,0xD0,0x6A,0x00,0x6A,0x00,0xFF,0xD6,0x5F,
0x5E,0x8B,0xE5,0x5D,0xC3,0x55,0x8B,0xEC,0x83,0xEC,0x10,0x53,0x56,0x8B,0xF1,0x89,
0x55,0xF0,0x33,0xD2,0x57,0x8B,0x46,0x3C,0x8B,0x5C,0x30,0x78,0x03,0xDE,0x89,0x5D,
0xF4,0x8B,0x4B,0x20,0x03,0xCE,0x39,0x53,0x18,0x76,0x39,0x8B,0x39,0x33,0xC0,0x03,
0xFE,0x8A,0x1F,0x84,0xDB,0x8B,0x5D,0xF4,0x74,0x1C,0x8B,0xD8,0x8A,0x07,0x6B,0xDB,
0x21,0x0F,0xBE,0xC0,0x03,0xD8,0x47,0x8A,0x07,0x84,0xC0,0x75,0xF1,0x89,0x5D,0xF8,
0x8B,0x5D,0xF4,0x8B,0x45,0xF8,0x3B,0x45,0xF0,0x74,0x12,0x83,0xC1,0x04,0x42,0x3B,
0x53,0x18,0x72,0xC7,0x33,0xC0,0x5F,0x5E,0x5B,0x8B,0xE5,0x5D,0xC3,0x8B,0x43,0x24,
0x8D,0x04,0x50,0x0F,0xB7,0x0C,0x30,0x8B,0x43,0x1C,0x8D,0x04,0x88,0x8B,0x04,0x30,
0x03,0xC6,0xEB,0xE2
};

对于ShellCode能不能在各个电脑上都适用,我还不敢保证,因为我之前也尝试将别人写的拿过来运行,但是程序崩溃。所以最好自己试着写一遍。

ShellCode字符也可以写成这种形式:

char shellcode[] =
"\x55\x8b\xec\x51\x51\x83\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89"
"\xf3\x8d\x4e\x08\x31\xd2\xcd\x80\xe8\xe4\xff\xff\xff\x2f\x62\x69\x6e"
"\x2f\x73\x68\x58"; //...

它利用的是\x的转义字符特性,其实是一样的。

写好ShellCode后就该调用它了

方法1:利用动态申请内存,一定是可执行属性

typedef void (_stdcall *CODE)();

VOID Sub_1()
{
PVOID p = NULL;
p = VirtualAlloc(NULL, sizeof(ShellCode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (p == NULL)
{
return;
}
memcpy(p, ShellCode, sizeof(ShellCode)); CODE code = (CODE)p;
code();
}

方法2,:强制类型转换成函数指针

VOID Sub_2()
{
((void(WINAPI*)(void))&ShellCode)();
}

虽然看上去有点复杂,但是拆开分析一下还是很简单的,首先取了ShellCode的地址,将它强制类型转换成函数指针,第一个void表示函数返回值,第二个void可以不要,它是说该函数没有参数,最后在后面加上小括号,注意WINAPI的调用约定一定不能少,我用的VS2015编译器,写的控制台程序的默认调用约定是_cdecl。

方法3:嵌入式汇编呼叫ShellCode

#pragma comment(linker, "/section:.data,RWE")
VOID Sub_3()
{
__asm
{ mov eax, offset ShellCode
jmp eax }
}

这种方法写法也比较灵活,其中第一句 mov eax, offset ShellCode 可以用 lea eax, ShellCode 代替,因为它们是等价的

第二句的 jmp 也可以用 call 代替。所以就是四种组合了。

最上面的一句 #pragma comment(linker, "/section:.data,RWE") 是很重要的,我曾经因为没有它,而导致多次错误,却一直在ShellCode上找原因。

它也是说将这段代码放入可执行区域。

方法4:伪指令


#pragma comment(linker, "/section:.data,RWE"
VOID Sub_4()
{
__asm
{ mov eax, offset ShellCode
       ;_emit 伪指令在当前文本段落的当前位置定义一个字节。 _emit 伪命令类似于 MASM 的 DB 指令。
_emit 0xFF
_emit 0xE0 }
}

这种方法虽然可以成功执行,但是我也不知道0XFF,0XE0 起到了什么作用。

 

ShellCode的几种调用方法的更多相关文章

  1. php分页类的二种调用方法(转载)

    php分页类的二种调用方法 原文地址:http://www.xfcodes.com/php/fenye/25584.htm 导读:php分页类的二种调用用法,ajax调用php分页类,非ajax方式调 ...

  2. Hutool工具里,POST方法,body中传参的几种调用方法

    接口说明: POSTMAN测试: JAVA代码: package com.provy.guard.api; import java.util.HashMap; import java.util.Map ...

  3. opencv2.4中SVD分解的几种调用方法

    原帖地址: http://blog.sina.com.cn/s/blog_6109b5d00101ag7a.html       在摄影测量和计算机视觉中,考虑最优解问题时,经常要用到SVD分解.奇异 ...

  4. JavaScript函数的4种调用方法详解

    在JavaScript中,函数是一等公民,函数在JavaScript中是一个数据类型,而非像C#或其他描述性语言那样仅仅作为一个模块来使用.函数有四种调用模式,分别是:函数调用形式.方法调用形式.构造 ...

  5. JavaScript 函数的4种调用方法

    JavaScript 函数有 4 种调用方式. 每种方式的不同方式在于 this 的初始化. 作为一个函数调用 function myFunction(a, b) { return a * b; } ...

  6. WebService两种调用方法

    1.wsimport生成本地客户端代码 命令提示窗口执行生成命令. 格式:wsimport -s "src目录" -p “生成类所在包名” -keep “wsdl发布地址” 示例: ...

  7. thinkphp的钩子的两种配置和两种调用方法

    thinkphp的钩子行为类是一个比较难以理解的问题,网上有很多写thinkphp钩子类的文章,我也是根据网上的文章来设置thinkphp的钩子行为的,但根据这些网上的文章,我在设置的过程中,尝试了十 ...

  8. MFCdll的两种调用方法

        有同事问我mfcdll的掉用方法,这里总结了一下.   1 lib库调用   只要VS能找到dll对应的lib和h文件,就可以开发和调试.包含lib和h文件有两个方法. 第一种方法设置路径是 ...

  9. 008.Delphi插件之QPlugins,服务的两种调用方法

    这个QPlugins自带的DEMO,大概的意思就是,创建2个服务类,程序启动的时候注册这2个服务类.点击不同的按钮,使用不同的方法来调用这个服务. 效果界面如下 unit Frm_Main; inte ...

随机推荐

  1. imfilter与fspecial

    saliencyMap = imfilter(saliencyMap,fspecial('gaussian',round(scale/64*3),min(scale/64*3*5/4))); fspe ...

  2. HUAS 1483 mex(离线+线段树)

    实在是太弱了.... 考虑离线,从mex[l,r]向mex[l,r+1]转移,显然是没啥东西可以记录的... 从mex[l,r]向mex[l+1,r]转移,记x=mex[l,r],如果[l+1,r]不 ...

  3. 【二分】【P1314】 【NOIP2011D2T2】聪明的质监员

    传送门 Description 小T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有 \(n\) 个矿石,从 \(1\) 到 \(n\) 逐一编号,每个矿石都有自己的重量 \(w_i\) ...

  4. CSS的历史与工作原理

    1. 浏览器的发展与CSS 网页浏览器主要通过HTTP协议连接网页服务器而取得网页,HTTP容许网页浏览器送交资料到网页服务器并且获取网页.目前最常用的 HTTP 是 HTTP/1.1,这个协议在RF ...

  5. 如何将javascript对象转换成字符串

    将后台程序(如php)发送过来的json数据转化为javascript的数组或者对象的方法十分简单,代码如下: 1 // 假设后台发送的json数据为 '{a:2,b:1}' 存储于str中 2 va ...

  6. printf函数用法小记

    By francis_hao    Aug 26,2017   C语言中printf函数是一个比较常用的函数,但是常用并不代表完全了解,本文翻译了printf的man手册,介绍了其全部功能(不包括ma ...

  7. selenium测试-open chrome

    通过selenium来打开浏览器测试之前,需要确认本地已安装相应的webdriver,本例以chrome为例. 1. 查看本地chrome版本,以此确认需要安装的webdriver版本 查看chrom ...

  8. Codeforces Round #340 (Div. 2) A

    A. Elephant time limit per test 1 second memory limit per test 256 megabytes input standard input ou ...

  9. Android网络请求的时候报错 Connection refused 处理

    在用Android测试JSON数据解析的时候,报了这样一个异常: java.net.ConnectException: localhost/ - Connection refused 原来模拟器默认把 ...

  10. python2.6升级2.7导致yum无法使用 No module named yum

    这里有解决方法:https://teddysun.com/473.html 记住旧版本 Python 2.6.6 的重要路径如下所示,在运行 yum 命令的时候,会提示你哪个 module 不存在,不 ...