Ultrasn0w

From The iPhone Wiki
Revision as of 09:38, 4 July 2009 by Oranav (talk | contribs) (Added ultrasn0w code loader with comments)
Jump to: navigation, search

ultrasn0w (previously: yellowsn0w) is the only iPhone 3G unlock payload. yellowsn0w was released on 01/01/09 [1]. ultrasn0w was released on June 23th 2009 [2].

Credit

MuscleNerd, and The dev team

Exploit

Relies on an unsigned code injection vulnerability.

The actual unlock works by a daemon patching the baseband's RAM on-the-fly, overriding the carrier lock code. It is not permanent because of the signature checks - the bootloader has to pass the sigchecks and the baseband has to pass them too, so any change to the baseband/bootloader cannot be made.

Current Injection Vector

ultrasn0w refers to the reuseable payload, but it requires an injection vector in order to be inserted into the baseband. yellowsn0w was originally to be released with an injection vector that works on pre-2.28.00 baseband versions. However, geohot had an injection vector for 2.28.00 and the decision was made to release yellowsn0w with this injection vector to benefit the most people. This injection vector is discussed here. ultrasn0w uses a different injection vector - AT+XLOG Exploit.

ultrasn0w payload with comments (by Oranav)

Code loader (incl. Stage2)

ROM:00000000 ; =============== S U B R O U T I N E =======================================
ROM:00000000
ROM:00000000
ROM:00000000 code_loader
ROM:00000000 dest_addr = R1
ROM:00000000 src_addr = R6
ROM:00000000                 MOVLS   dest_addr, 0x110
ROM:00000004                 ADDS    dest_addr, #6
ROM:00000006                 LSLS    dest_addr, dest_addr, #8 ; unused ram to place code = 0x11600
ROM:00000008                 ADDS    R2, dest_addr, #1 ; thumbing
ROM:0000000A
ROM:0000000A loop                                    ; CODE XREF: code_loader+24�j
ROM:0000000A                 MOVLS   R0, 0x22 ; '"'
ROM:0000000E                 LDRB    R3, [src_addr]  ; first nibble
ROM:00000010                 CMP     R0, R3
ROM:00000012                 LDRB    R0, [src_addr,#1] ; second nibble
ROM:00000014                 BEQ     run             ; branch if end of string
ROM:00000016                 SUBS    R3, #0x41       ; subtract 'A'
ROM:00000018                 SUBS    R0, #0x41       ; subtract 'A'
ROM:0000001A                 LSLS    R3, R3, #4      ; make room for next nibble
ROM:0000001C                 ADDS    R3, R3, R0      ; put them together as a byte
ROM:0000001E                 STRB    R3, [dest_addr]
ROM:00000020                 ADDS    dest_addr, #1
ROM:00000022                 ADDS    src_addr, #2
ROM:00000024                 B       loop
ROM:00000026 ; ---------------------------------------------------------------------------
ROM:00000026
ROM:00000026 run                                     ; CODE XREF: code_loader+14�j
ROM:00000026                 BLX     R2              ; run payload
ROM:00000028                 MOVLS   R0, 0           ; safe exit
ROM:0000002C                 ADDS    dest_addr, R0, #0
ROM:0000002E                 BLX     R4
ROM:00000030                 MOV     SP, R5
ROM:00000032                 POP     {R0-src_addr,PC}
ROM:00000032 ; End of function code_loader

Old yellowsn0w payload w/ comments (by Darkmen) =

The exploit consists from 4 parts:

Code loader

ROM:00000000 ; =============== S U B R O U T I N E =======================================
ROM:00000000
ROM:00000000
ROM:00000000 loader
ROM:00000000                 LDR     R2, =0x11700    ; unused ram to place code
ROM:00000002                 ADDS    R4, R2, #1      ; thumb switch
ROM:00000004                 LDR     R3, =0x40159FBF ; at-handler buffer where stage2 binary and following hexdata are
ROM:00000006
ROM:00000006 copy.loop                               ; CODE XREF: loader+12�j
ROM:00000006                 LDRB    R0, [R3]        ; copying code+data until double quotes
ROM:00000008                 CMP     R0, #0x22 ; '"'
ROM:0000000A                 BEQ     run             ; jump thumb code
ROM:0000000C                 STRB    R0, [R2]
ROM:0000000E                 ADDS    R2, #1
ROM:00000010                 ADDS    R3, #1
ROM:00000012                 B       copy.loop       ; 
ROM:00000014 run                                     ; CODE XREF: loader+A�j
ROM:00000014                 BX      R4              ; jump stage2 code
ROM:00000014 ; End of function loader
ROM:00000014
ROM:00000014 ; ---------------------------------------------------------------------------

Stage2(tm)

RAM:00000000 ; =============== S U B R O U T I N E =======================================
RAM:00000000 stage2
RAM:00000000                 ADDS    R2, #0x10       ; R2 = 0x11700 + stage2 size
RAM:00000002                 MOVS    R7, #0xF
RAM:00000004                 BICS    R2, R7          ; align offset by 0x10
RAM:00000006                 ADDS    R7, R2, #0      ; saving address to jump
RAM:00000008                 ADR     R4, 0x44        ; skipping Stage2 size and taking first char from at-string
RAM:0000000A                 ADR     R5, char2byte   ; loading routine addr
RAM:0000000C                 ADDS    R5, #1          ; thumb
RAM:0000000E
RAM:0000000E loop                                    ; CODE XREF: stage2+2C�j
RAM:0000000E                 LDRB    R1, [R4]        ; at-string[index]
RAM:00000010                 CMP     R1, #'x'        ; end of line?
RAM:00000012                 BEQ     jump_code
RAM:00000014                 BLX     R5              ; char2byte first hakfbyte
RAM:00000016                 LSLS    R3, R1, #4      ; <<4 0X becoming X0
RAM:00000018                 LDRB    R1, [R4,#1]     ; at-string[index+1]
RAM:0000001A                 BLX     R5              ; char2hex second halfbyte
RAM:0000001C                 NOP
RAM:0000001E                 NOP
RAM:00000020                 NOP
RAM:00000022                 NOP
RAM:00000024                 ADDS    R1, R1, R3      ; R1 = complete byte
RAM:00000026                 STRB    R1, [R2]        ; storing byte to dst
RAM:00000028                 ADDS    R4, #2          ; hexstr_index+=2
RAM:0000002A                 ADDS    R2, #1          ; dst++
RAM:0000002C                 B       loop            ; at-string[index]
RAM:0000002E jump_code
RAM:0000002E                 NOP
RAM:00000030                 NOP
RAM:00000032                 ADDS    R7, #1          ; thumbing
RAM:00000034                 BX      R7              ; run Task creator code
RAM:00000034 ; End of function stage2
RAM:00000038
RAM:00000038 ; =============== S U B R O U T I N E =======================================
RAM:00000038 char2byte                               ; DATA XREF: stage2+A�o
RAM:00000038                 CMP     R1, #0x41 ; 'A'
RAM:0000003A                 BGE     letter          ; letter to number
RAM:0000003C                 SUBS    R1, #0x30 ; '0' ; digit to number
RAM:0000003E                 BX      LR
RAM:00000040 letter                                  ; CODE XREF: char2byte+2�j
RAM:00000040                 SUBS    R1, #0x37 ; '7' ; letter to number
RAM:00000042                 BX      LR              ; ret
RAM:00000042 ; End of function char2byte

Task creator

RAM:000119A0 ; =============== S U B R O U T I N E =======================================
RAM:000119A0
RAM:000119A0
RAM:000119A0 handler_replace
RAM:000119A0                 LDR     R0, =0x4011714C ; soft reset handler addr
RAM:000119A2                 ADR     R1, new_handler
RAM:000119A4                 ADDS    R1, #1          ; thumbing
RAM:000119A6                 STR     R1, [R0]        ; setting new handler
RAM:000119A8                 POP     {R0-R4,PC}      ; safe exit fixing stack
RAM:000119A8 ; End of function handler_replace

RAM:000119B0 ; =============== S U B R O U T I N E =======================================
RAM:000119B0
RAM:000119B0
RAM:000119B0 new_handler                             ; DATA XREF: handler_replace+2�o
RAM:000119B0                 PUSH    {R4-R7,LR}
RAM:000119B2                 LDR     R3, =0x403BB344 ; jamptable var
RAM:000119B4                 MOVS    R6, #0x80
RAM:000119B6                 SUB     SP, SP, #0x2C
RAM:000119B8                 LSLS    R6, R6, #4      ; 0x200
RAM:000119BA                 STRH    R0, [R3]        ; saving R0 to mem var
RAM:000119BC                 STR     R1, [SP,#0x40+resp_string] ; saving responce prt to stack
RAM:000119BE                 LDR     R4, =0x201420AC ; malloc
RAM:000119C0                 ADDS    R0, R6, #0
RAM:000119C2                 BLX     R4              ; malloc(0x200)
RAM:000119C4                 MOVS    R5, #0
RAM:000119C6                 STR     R0, [SP,#0x40+ptr_200] ; saving pointer to stack
RAM:000119C8                 MOVS    R0, #0x98       ; sizeof(NU_TASK)
RAM:000119CA                 BLX     R4              ; malloc(0x98)
RAM:000119CC                 ADDS    R7, R0, #0      ; R7 = task
RAM:000119CE                 STR     R5, [R0,#0xC]   ; task.field=0
RAM:000119D0                 MOVS    R0, 0x100
RAM:000119D4                 BLX     R4              ; malloc(0x100)
RAM:000119D6                 MOVS    R2, #0x80
RAM:000119D8                 LDR     R1, =task_loop  ; src
RAM:000119DA                 LSLS    R2, R2, #1      ; size to copy
RAM:000119DC                 LDR     R3, =0x203C58A0 ; bytecpy
RAM:000119DE                 ADDS    R4, R0, #0      ; R4 = dyn_task_loop
RAM:000119E0                 BLX     R3              ; bytecpy(task_loop, dyn_task_loop, 0x100)
RAM:000119E2                 LDR     R3, [SP,#0x40+ptr_200]
RAM:000119E4                 STR     R3, [SP,#4]     ; void *stack_address = malloc(0x200)
RAM:000119E6                 MOVS    R3, #0x44
RAM:000119E8                 STR     R3, [SP,#0xC]   ; priority = 0x44
RAM:000119EA                 MOVS    R3, #0xA
RAM:000119EC                 ADDS    R4, #1          ; thumbing dyn_task_loop
RAM:000119EE                 STR     R3, [SP,#0x14]  ; preempt = NU_PREEMPT
RAM:000119F0                 MOVS    R3, #0xC
RAM:000119F2                 ADDS    R2, R4, #0      ; void(*task_entry)
RAM:000119F4                 STR     R3, [SP,#0x18]  ; auto_start = NU_START
RAM:000119F6                 LDR     R1, =devteam1   ; char *name
RAM:000119F8                 STR     R5, [SP]        ; void *argv = 0
RAM:000119FA                 STR     R6, [SP,#8]     ; stack_size = 0x200
RAM:000119FC                 STR     R5, [SP,#0x10]  ; time_slice = 0
RAM:000119FE                 ADDS    R0, R7, #0      ; NU_TASK *task
RAM:00011A00                 MOVS    R3, #0          ; int argc = 0
RAM:00011A02                 LDR     R4, =0x203FB540 ; NU_Create_Task
RAM:00011A04                 BLX     R4              ; status = NU_Create_Task()
RAM:00011A06                 ADDS    R2, R0, #0
RAM:00011A08                 CMP     R0, #0          ; success = zero
RAM:00011A0A                 BNE     status_error
RAM:00011A0C                 LDR     R1, =OK
RAM:00011A0E                 LDR     R0, [SP,#0x40+resp_string]
RAM:00011A10                 LDR     R3, =0x2046DD00 ; sprintf
RAM:00011A12                 BLX     R3              ; sprintf(resp_string,"OK")
RAM:00011A14                 B       exit            ; fixing stack
RAM:00011A16 ; ---------------------------------------------------------------------------
RAM:00011A16
RAM:00011A16 status_error                            ; CODE XREF: new_handler+5A�j
RAM:00011A16                 LDR     R1, =ERROR
RAM:00011A18                 LDR     R0, [SP,#0x40+resp_string]
RAM:00011A1A                 LDR     R3, =0x2046DD00 ; sprintf
RAM:00011A1C                 BLX     R3              ; sprintf(resp_string,"ERROR")
RAM:00011A1E
RAM:00011A1E exit                                    ; CODE XREF: new_handler+64�j
RAM:00011A1E                 ADD     SP, SP, #0x2C   ; fixing stack
RAM:00011A20                 POP     {R4-R7,PC}      ; bye
RAM:00011A20 ; End of function new_handler
RAM:00011A20
RAM:00011A20 ; ---------------------------------------------------------------------------

Unlock task loop

RAM:00011A64 ; =============== S U B R O U T I N E =======================================
RAM:00011A64
RAM:00011A64 task_loop                               ; DATA XREF: RAM:off_11A2C�o
RAM:00011A64                 PUSH    {R4,R5,LR}
RAM:00011A66                 LDR     R5, =0x40232754 ; sec mailbox
RAM:00011A68                 SUB     SP, SP, #0x14
RAM:00011A6A
RAM:00011A6A loop                                    ; CODE XREF: task_loop+44�j
RAM:00011A6A                 LDR     R3, =0x20165998 ; NU_Receive_From_Mailbox
RAM:00011A6C                 ADDS    R0, R5, #0      ; NU_MAILBOX *mailbox
RAM:00011A6E                 MOV     R1, SP          ; void *Message
RAM:00011A70                 MOVS    R2, #0xFF       ; Timeout
RAM:00011A72                 BLX     R3              ; NU_Receive_From_Mailbox(sec_mailbox,SP,0xFF)
RAM:00011A74                 LDR     R3, [SP]        ; Message[0]
RAM:00011A76                 CMP     R3, #0xD        ; Message[0] = 0xD ?
RAM:00011A78                 BNE     skip            ; 
RAM:00011A7A                 LDR     R1, [SP,#4]     ; Message[1]
RAM:00011A7C                 LDR     R3, =0x402F79BC
RAM:00011A7E                 LDR     R2, [R1]        ; Message[1].field0
RAM:00011A80                 STR     R2, [R3]        ; sec_task_var1 = Message[1].field0
RAM:00011A82                 ADDS    R3, #4          ; 0x402F79C0
RAM:00011A84                 LDR     R2, [R1,#4]     ; Message[1].field1
RAM:00011A86                 STR     R2, [R3]        ; sec_task_var2 = Message[1].field1
RAM:00011A88                 LDR     R2, [R1,#8]     ; Message[1].field2
RAM:00011A8A                 LDR     R3, =0x100FF00
RAM:00011A8C                 STR     R3, [R2]        ; Message[1].field2[0] = 0x100FF00
RAM:00011A8E                 LDR     R3, =0x4020401
RAM:00011A90                 STR     R3, [R2,#4]     ; Message[1].field2[1] = 0x4020401
RAM:00011A92                 LDR     R3, =0x4040403
RAM:00011A94                 STR     R3, [R2,#8]     ; Message[1].field2[2] = 0x4040403
RAM:00011A96                 MOVS    R3, #1
RAM:00011A98                 STR     R3, [R1,#0xC]   ; Message[1].field3 = 1
RAM:00011A9A                 MOVS    R3, #0x20       
RAM:00011A9C                 STR     R3, [SP]        ; Message[0] = 0x20
RAM:00011A9E
RAM:00011A9E skip                                    ; CODE XREF: task_loop+14�j
RAM:00011A9E                 ADDS    R0, R5, #0      ; sec mailbox
RAM:00011AA0                 MOV     R1, SP          ; void *Message
RAM:00011AA2                 MOVS    R2, #0xFF       ; timeout
RAM:00011AA4                 LDR     R3, =0x203ED568
RAM:00011AA6                 BLX     R3              ; NU_Send_To_Mailbox()
RAM:00011AA8                 B       loop            ; NU_Receive_From_Mailbox
RAM:00011AA8 ; End of function task_loop

Source Code

The source code for yellowsn0w 0.9.1 (old version) was released along with yellowsn0w release. [3]

See Also

External links