异或也许很多人都听说过, 我想一般人想到异或应该就是值与值比对相同为0,不同为1
。比如:1 ^ 1 = 0;0 ^ 1 = 1。那事实上就是这么一回是哈哈, 也许我们平时碰不到异或, 但是在计算机中异或在底层是很常用的。
这一部分的话很好理解,因为现在的各大杀软厂商对于常见的渗透框架,恶意payload都做了特征码
的记录。那么, 只要我们的shellcode跟这个特征码匹配上, 那么没有例外, 直接凉凉。所以, 我们需要通过一种方式来混淆shellcode让它原本的特征码被隐藏,从而达到免杀的效果。
在这里我们要关注的一点是特征码
, 在免杀这一环节, 特征码
是很重要的, 我们做的所有的事情就是为了让特征码
消失。
这里插一句, py是全世界最好的语言, 简洁的语法让人欲罢不能。但是万物有始有终, 再简洁的语法, 最终也逃不过C的魔爪。所以, C语言YYDS, 希望有生之年我能学的不像现在这么扣脚。
对于C来说, 所有的字符不过是一个数字而已, 但在py中我们无法像C那样直接对字符(字符串)进行操作。我们要对python中的字符串做异或需要对字符做一下转码。
ord(): 字符转ASCII
chr():ASCII转字符
以下面为例子做简单的异或讲解:
# 对字符串异或 string = "hello world" # 要异或的字符串 key = 20 # 用于异或的key def enc(string, key): result = '' # 用来接收异或后的值 for i in range(len(string)): result += chr(ord(string[i]) ^ key) return result data = enc(string, key) print(data) # 结果:|qxx{4c{fxp # 对异或后的字符串解密 # 还原的话很简单,在对加密结果异或一下就还原了 print(enc(data, key)) # 结果:hello world
以上的话就是简单的对字符串做异或, 在这里, 我想应该会有想法了, 我们可以把“hello world”替换为shellcode, 得到结果后放入调用代码里,用异或还原一下即可。再还原之前也许被查杀的shellcode这时已经不会再被查杀了。
原理: 对原本字符串按照加密key的长度分组, 每组长度都相同, 然后再用key对每组字符串循环异或。
分段异或加密的话其实挺简单的(虽然简单, 但是我也琢磨了一小阵子, 我太菜了),这里我贴上代码。
def enc(string, key): result = '' if len(string) % len(key) == 0: # 能整除的情况 # 给字符串分组 for i in range(int(len(string)/len(key))): # 按照key的长度循环异或 for j in range(len(key)): # string[i*len(string)+i] = # i为分组位置, j为分组的下标 result += chr(ord(string[i*len(key)+j]) ^ ord(key[j])) else: # 无法整除的情况 # 给字符串分组 for i in range(int(len(string)/len(key))): # 按照key的长度循环异或 for j in range(len(key)): # string[i*len(string)+i] = # i为分组位置, j为分组的下标 result += chr(ord(string[i*len(key)+j]) ^ ord(key[j])) for m in range(len(string) % len(key)): # m为要异或的下标位置, int(len(string)/len(key))*len(key)为计算要异或的值从哪里开始 result += chr(ord(string[m+int(len(string)/len(key))*len(key)]) ^ ord(key[m])) return result if __name__ == '__main__': string = "hello world!1" key = "pass" result = enc(string, key) print(enc(result, key))
好啦, 到这里异或就结束了, 如果觉得内容不错,有兴趣的话可以扫码加入知识星球(ILU的秃头路线)喔!