Okay, I'm from China. The title of my presentation is Hacking Windows C. It's about the security problems of PDAs and mobiles. My presentation is constructed with eight parts. First of all, I'll make a brief introduction of Windows C, because ARM processors is the most useful processor in PDAs and mobiles, so I'll introduce the ARM processor's architecture. You know, understanding memory management is very important for Buffalo Flow. The second, I'll introduce memory management with graphics. Compared with other Windows systems, Windows C chooses processes in a different way. Then I'll introduce the features of processes and threads of Windows C. The Windows C API search technology is funny. I'll introduce how to write shellcode using this method. And I will also introduce the implementation of system code and use it to write shellcode. After this, I'll demonstrate a simple Buffalo Flow. Well, I think this technology will be improved in the future. Then I'll talk something about decoding shellcode. The decoding shellcode will make the real shellcode more universal, but ARM processor's cache architecture makes it funny. At last, I'll conclude my presentation. Okay, let's move on to the next part, the first part. Windows C is a very popular embedded operating system for PDAs and mobiles. The name is developed by Microsoft. Because of the familiar APIs, Windows developers can easily develop applications for Windows C. Maybe this is a very important reason that makes Windows C popular. Windows C file is the latest version, but Windows C.net is the most useful version, and my presentation is based on this version. Maybe for marketing reasons, there is Windows mobile software for pocket PC and a smartphone in Microsoft's website and MSDN, but they are all based on the core of Windows C. By default, Windows C is in little Indian mode and it supports several processes. Almost all of the embedded devices will use ARM CPU. ARM processor is a typical RISC processor, which implements a load store architecture. Only load and store instructions can access memory. Data operating instructions operate on RISC contents only. There are six major versions of ARM architecture. The demonstrated device has a Samsung S3 C2410 processor, which has an ARM 9 core and the architecture version is an ARM V4T. More and more PDAs are using Intel X scale processor, which architecture version is V5TE. ARM processors support seven processor modes, depending on the architecture version. These modes are user, FIQ, IRQ, supervisor, undefined, abort and system. The system mode requires ARM architecture V4 and above. All modes except the user mode are referred to privileged mode. Applications usually are running user mode, but on the pocket PC, all applications appear to be running in kernel mode. I'll talk about it later. Windows ARM processor has 39 registers. These registers are arranged in partially overlapping banks. There's different registers for each processor mode. The bank registers give rapid context switching for dealing with processor exception and privileged operations. In ARM architecture V3 and above, there are 30 general purpose registers, the program counter register, the current program status register and the file saved program status register. 15 general purpose registers are visible at any one time, depending on the processor mode. By convention, R13 is used as a stack point in ARM assembly language. The C and the C++ compilers always use R13 as a stack point. In user mode and system mode, R14 is used as a link register, which stores the return address while a subroutine call is made. The program counter register is accessed as R15. It can access directly by data processing instructions. This feature is different from other processors and it is useful for code location while writing show code. You know, understanding memory management is very important for buffer overflow. But Windows C, but compared to other Windows systems, Windows C chooses memory management in a different way. Windows C uses ROM and RAM. The ROM in the Windows C system is just like a small read on a hard disk. It stores the entire operating system as well as the applications that are bundled in the system. The data, um, the data can maintain inside the ROM without power or battery. The RAM in a Windows C system is divided into two areas. The program memory and object store. The object store can be considered something like a permanent virtual RAM disk. It's unlike a RAM disk in the PC. It can maintain the files in it, uh, even if the system turned off. That, that is the reason that, this is the reason that Windows C devices typically have a main battery and a backup battery. They provide the power to my, to the RAM to maintain the files stored in it. Even when the user hit the reset button, the Windows C kernel starts up looking for previously created object store. Um, the system will use that store if it finds one. Another area of Windows C RAM is program memory. Program memory is just like the RAM in the PC. Uh, it stores the heaps and the stacks that, uh, the application, for applications that are running. Um, the, the dividing of the, between the object store and the program memory is adjustable. The user can move the dividing line, uh, by the system control panel applet. Windows C is a, um, 32-bit operating system, so it supports 4GB virtual address space. Let's look at this graph. This is the, um, 4GB virtual address space layout. The upper 2GB is, uh, used for, used by, is a kernel space used by a system for its own data. And the lower 2GB is a user space. From this address, uh, to below this address, the memories are used to, um, um, uh, larger memory, larger memory allocation. Such a, uh, it's used by the, uh, such as memory mapped files. Um, um, object store is loaded here. And from zero to below, this, uh, uh, this memory is, uh, divided into 33 slots. Each of which is a 32MB. The slot 1 is, uh, uh, XIP, uh, executed in place. This is a new feature, uh, of the Windows C.net. Uh, it expanded the application's virtual address space from 32MB to 64MB. Well, this graph is, uh, is the slot 0 virtual address space layout. Slot 0 is very important. It's, uh, used by the current active process. The first 64KB is, uh, reserved by the OS. And the following is the process's code, code and data. Um, stacks and heaps are arranged here. DLL files are loaded into the top, uh, top address. Well, let's move on to the next part. Um, uh, compared with other, uh, system, Windows C.net chooses processes in a different way. Windows C.net limits, uh, 32 processes being run at any one time. Uh, when the system starts, at least four processes are created. Um, let's look at the previous, uh, graph. NKEXE, uh, which provides the kernel service. It's always loaded into the slot 97. Um, filesystem.exe, which provides the filesystem service. It's always in slot 2. Device.exe, which, uh, which, uh, load and maintains the device drivers for system. It's in slot 3 normally. And, uh, GWES.exe, which provides GUI support. The other processes are also created such as explorer. Um, the, uh, other Windows system. Each process, at least, has a primary thread, uh, associated it, uh, up on start. Uh, if it never, never created one. One process, uh, can create any number of threads only limited by the available memory. Um, each thread belongs to a particular, uh, process and shares the same memory. But the, uh, set prog permissions API, uh, can give the, um, current thread access any, any process. Each thread has an ID, a private stack, and a set of registers. When the process is, uh, loaded, uh, the system will assign the next, uh, available slot to it. And DL files loaded into the top address of the, um, uh, uh, uh, address space. And then followed by the stack and the default process heap. After this, then execute it. Uh, when the, uh, when the process is, the thread is scheduled, the system will copy, uh, copy from its slot to slot zero. It's not a real copy operation, it's just mapped into the slot zero. Uh, this is mapped back to the original slot allocated to the process if the process becomes inactive. Process, uh, allocated stack for each thread. The default size is, uh, 64 KB, uh, depending on the link parameter when the, uh, program is compiled. This, uh, this size can, can, can be modified. The top two KB is used to guard against the stack overflow. We can't destroy this memory, otherwise the device will freeze. And the remainder, uh, available for use. Um, variables declared inside the function are allocated in the stack. Um, thread stack memory is reclaimed when it terminates. Well, let's move on to the next part. Um, before, before exploit, we must have, uh, share code to run on the Windows CE. Um, Windows CE implements, uh, V32 compatibility. The core DLL provides the entry points for, uh, for the, for almost all the APIs that implement, uh, that in the core DLL. Um, um, um, we must, uh, search the, uh, necessary API addresses, um, and then you use this, uh, uh, API address, APIs to implement our share code. The traditional method to implement, uh, uh, share code, uh, in the, uh, other Windows system is to, uh, locate the kernel 32 or NTDL, uh, via PB structure and then search, uh, search necessary APIs via, uh, P head structure. Well, is there any structure like, um, PB on the Windows CE? The answer is yes. That's, um, the kernel, the, uh, K data structure will satisfy those. The defined in NK arm.h. Uh, K data structure is, uh, is a very important kernel, uh, kernel structure can be accessed from user mode by fixed, uh, address, uh, K user, uh, P user K data. Um, the value over, uh, the value over P user K data is defined in the, uh, K functs. It's in the normal SDK. Um, uh, the value, uh, the P user K data is, uh, FFFC800 in ARM processors and, uh, file 8, uh, file 8, uh, file 8, uh, file 8, uh, file 8, uh, file 8, uh, file 8, 800 on the, uh, other CPUs. Well, let's look at the last member of, uh, K data structure. Um, it's offset 300 from the start of K data structure. Um... There is, uh, the, uh, the, uh, the, um, AIN4 is a DWORD array and there is a point to the module list index 9. So offset 3 to 4 from the FFFC800 is the point to the module list. Well, let's look at the module structure. The first member is defined in kernel header file. The second member is P mode. It's a point to the next module of the module chain. The third member is LPSZ mode name. It's a module name string. So we can locate the core DLL by comparing the unicode string of its name. Well, we also notice the E32 member. Let's look at this. E32 member is the E32 structure. It's defined in kernel header file. The third member is P HDR. Well, let's look into the E32 structure. The E32 V base will tell us the virtual base address of the module. So we can locate the virtual base address of the core DLL. We also notice the last member is E32 unit. It's an info structure and the info structure has two members. The first is the virtual relative address and the second is the size. And the little extra is defined in the P HDR. The start of P HDR. Six members used by NK. And the first is the export table position. So from now on, we got the virtual base address of the core DLL and its export table relative address of the export table position. And I wrote a small... I wrote a small program to list all the virtual base address of all loaded DLL files. This is the KData structure. And offset 324 is a point to the module structure. And the module structure is the chain structure. The offset 4 will point to the next module. So what is the point to the module structure? Well, the point to the module structure is in the kernel space. So this program only... this program only executed in the kernel mode. The user mode... it will fail in the user mode. Well, the most of the PC ROMs were built with the full kernel mode option. That's the applications all running kernel mode. So... so this small program will execute in the most of the pocket PC. I used this program to call the virtual base address of the core DLL is 1F6000. But when I use the EBC debug to look into, this address is invalid. The valid data is from 1F61000. I think maybe the Windows C is just for the purpose to... purpose over memory and start time and then load the head of the DLL file. Okay. The VNCE4.dust uses ordinals to find the API address. But I think use API name to find the... to find the API address is more reliable for share code. Because the API name won't change even if the core DLL file is changed. Well, we can... because we have the export table position and the base address of the core DLL. So we can use the... we can compare the image export directly to find the API address via API name. To save size, we can use the hash technology that from the LSD's V32 assembly components. And this is... this graph is ripped from LSD's V32 assembly components too. And it shows the way to locate the base address via API name. Well, let's move on next part. The test ASM is our final share code. It constructs with three parts. First, it will call get export section to get the virtual base address of the core DLL and its relative virtual address over export table position. And then it uses find function to find the API address via the hash value over the API name. And then stores the... find the... store the API address to the... its own hash value position. The last part is our implementation of our share code. It will change the register key over Bluetooth and then use kernel IO control to soft restart it. This share code will open the Bluetooth over some... we must notice the some... some assembly LDR pseudo instruction. Here, what I comment of this instructions. Because... because this pseudo instruction will be this in the EVC debug. It depend on the program. So, it won't get the FFF C800 in the share code. So, this instruction will make the share code fail. And the next instruction will be this in the EVC debug. It's okay. Well, in Windows CE, the R3 and... R0 and R3 use the first to fourth parameters of the API. If the... if the parameter is larger than four, the other parameters will store in the stack. So, we must pay attention while writing share code. Because the... because the share code always in the stack... stack memories. Well, EVC debugger has some bugs that make... make debugger difficult. The first, EVC will change the stack contents when the stack... in the end of the function. Well, it's... it's difficult to debug the buff overflow. Because the share code may be changed. And the instruction or the break point may be changed to E600010 in EVC sometimes. Well, it's... it's very bothering. And EVC allows the code to modify the text segment without error while... while using break point or you... when you step by step to debug into. But sometimes it's useful. Well, the... the... for the ARM debugger also have this... also have this bugs. So, I think maybe this is a bug of the debugger API over Windows CE. Maybe. Well, let's move on to the next part. The above share code we talked is complicated and it can't run in user mode. Is there any... is there any other method to implement share code? Well, let's look at an API implemented in the core DLL. Well, let's look at the power of the system. It has no parameters. The first... the system will check the... check the kthread info structure. And the kthread info is initialized in the MD created thread two function in the... in the MD... in the MD ARM.c. If the... if the application running kernel mode, this value will... the kthread info will be set with one. Otherwise, this value is saved zero. So, it tests this memory is one. Because the... if this... if this... if kthread info is one, then the system will use the API... API set table to find the real... real implement... implementation in the kernel space. If you... if your application is running... running kernel mode and this... this instruction will execute the... the R1 is the... is start from the eight... blah, blah, blah. It's in the kernel space. Otherwise, if the... if the kthread info is zero, the system will use this. This is... is the system call over Windows C. The system call number is from F... F0000 to F001000. There is a formula to... to determine the API... determine the system call number. It's like this. So... use this formula, we can calculate the system call number. Well, let's calculate the kernel IO control. Kernel IO control is in the... is defined in the k... kvim32.c. And the API set is... is zero. And the index is 99. So... so we calculated the system call number is like this. F0000FE74. Well, it's a... it's a... the system call number is more stable... more stable than the API address that implement in the core DL. Because... because the variable compile the ROM, the... the API address is a variable. So this... this share code is very simple. It only uses the system call to system call to... so... so this... this share code will... can execute in the user mode. But also the kernel mode. So I think this share code will use in the smartphone. The smartphone... the smartphones ROM not build... not build with the full kernel mode option. And the Microsoft device emulators ROM has... has no this option too. I tested this... this... this share code success in the Microsoft device emulator and my demonstrated device. Okay. Let's move on to the next part. The hello CPP is my... is my demonstrated vulnerable program. And it... it reads the... it reads the bin file of the root... root directory by F read. And then read this... read the file to the stack... stack variable buff. And the... the buff is only 512 bytes. So if the bin file is larger than 512 bytes, the... the program will overflow. And the print F and get a chart is just for test. They have no effect without the console DL in Windows directory. The console DL... the console DL can obtain from Windows mobile and developer power toy or from the pocket console. Windows C uses BL to... to call a function. And in the hello function, this is the first instruction. The store AOR to SP. It will store the AOR address to the stack port... to the stack... to the stack which contains the hello callers address. And... and the AODMIRSP2PC is the latest instruction in the hello function. It... this... this instruction will load the... load the AOR rest that is stored in the stack to the PC rest. And then the program will flow to the... will flow to the remain function. It will... then it will return. So overflow the AOR rest that stored in the stack. We will obtain the control while the function returned. The variables memory... the variables memory address that allocated by the program is corresponding to the loaded slot. Both the stack and the heap. The process may be loaded into the different slot each start time. So the base address of the slot always alters. But we know that the slot zero is mapped from the current process slot. So it's a stack address is stable. Anyway you can use the... use a jumper... jumper address. Jumper instruction address to let your... let the program flow to your shellcode. Well I tried two methods to construct the exploit path. The first is like this. The first... the start is the pad instructions and then is the return address. That we overflow it and then this return address is our... is pointed to our shellcode. Well, this is... this exploit path is larger. The PDA is frozen when the hello program is executed. I think maybe there are two reasons. The first is that the stack of Windows C is small and maybe the overflow destroyed the 2KB guard on the top of the stack boundary. So I changed it to another method to construct the exploit path. It's like this. I moved the shellcode in the start position and then the last is the... is the return address that pointed to our shellcode. Well, I used this method of success. I'll demonstrate it. Okay. The first... the Bluetooth is closed and I'll... I'll execute hello. It will print the... it will print the address of the path and the size. When I press any key, the... the device is restarting. Well, it has restarted. Well, after the system restart, the Bluetooth is open. Well, I'll... I'll close it because it's danger. Okay. Let's talk something about the decoding shellcode. The above shellcode that we talked is the concept shellcode. It contains a lot of zero. Well, the other vulnerable programs may be filled with a special characters before the stream buffer flow in some situations. For example, overflowed by SDR copy. It's difficult and inconvenient to write a shellcode without a special... without a special characters because if you use the R0, the opcode will contain the... will contain this zero. So, we think about the decoding shellcode. The newer ARM processor has a hovered architecture which... which separates instruction cache and the data cache. This feature will improve the performance of the ARM processor but the self-modifying code is not easy to implement because it will affect by the ARM cache architecture and the processes... processor's implementation. Well, let's look at this... this shellcode. Well, this is the decoding shellcode for the... for the test. The last... the last four instructions is... is move the one to the R1 to R4 registers. And the beginning of... the first four instructions will modify the last instructions. It will make the value to 99 because the R1 is 99. So, the R1 and the two R4 registers will... will get the 99 in my... in my demonstrated device. Well, we... we can saw the... the last four instructions has modified. But... but it will need more... need more NOP instructions between the decoding... decoded shellcode and... and the real shellcode in the Intel X... Intel X scale processors. You can try it. And maybe only the R1 get the 99. I think maybe the... the ARMV file architecture has... has six pipelines and... and my demonstrated device only has... is the ARMV4. It has... it has five pipelines. Maybe the pipelines modify... effect the result. Well, let's look at another... another method. Well, in this method, the last four MOV instructions were... were encoded with the exclusive OR with the 88. And the start is... is... is the decode... is the decoding shellcode. It has a loop to... is that... to load... to load the encoded shellcode. To... to load one byte of encoded shellcode and... and then decode it. Then start it to the original position. Well... well, the R1 to R4 registers won't get the... the 1, even if you add a lot of instructions. Well, we saw the last four instructions is... is decoded. But they don't get the 1. So... so I think maybe the load instructions will trigger the cache... some trick... some feature over the cache architecture. So we must... need the... need to flush the I-cache or D-cache after... after the shellcode decode. Well, I think... the first I think about the system interrupt. I... I used the system interrupt success in the AX power PC and the Spark. But the SWI instructions in the Windows C is just nonsense. The... the SWI handle defined in the ARM trap is... it's... it's just a... moves the AOR rest to the PC. So it's just a... not instruction. Well, I tried to... I have to try another method. Because the pocket PC ROMs were built with the full kernel mode option. The applications running the kernel mode. So I think about the MCR instructions to flush the I-cache and the D-cache. The MCR instruction can access the... in the kernel mode only. But... but unfortunately, this... this method all failed. Okay, let's move on to the last part. The codes we talked about are the real life buffer flow example in Windows C. It's simple, but I think this technology will be improved in the future. Because the instruction cache and the decoding shellcode is not good enough. Well, the internet and the handset devices are growing quickly. The threats to PDAs and the mobiles becomes more and more serious. The patch of Windows C is more difficult and dangerous because the... the entire operating system is in the ROM. Contained in the ROM. And if you... if you want to patch the system for completely, you must flush the system... the system... you must flush the system... you must flush the... the ROM. And it is... it is danger and... it is danger and difficult for the normal customers. Well, I consulted a lot of people on the internet. It's all listed here. I'll show my special appreciation to Nestle, who helped... who helped me a lot. Well, that's the end of my presentation. Hope you enjoyed. And sorry my lame English. Thank you. Thank you.