Ultrasn0w

ultrasn0w (previously: yellowsn0w) is an iPhone 3G, iPhone 3GS and iPhone 4 (GSM) unlock payload. yellowsn0w was released on New Years Day 2009. ultrasn0w was released on June 23rd 2009.

Credit
MuscleNerd, and iPhone 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.

Injection Vectors

 * AT+stkprof Exploit - used by yellowsn0w to unlock X-Gold 608 baseband 02.28.00.
 * AT+XLOG Vulnerability - used by ultrasn0w to unlock X-Gold 608 baseband 04.26.08.
 * AT+XAPP Vulnerability - used by ultrasn0w 1.0-1 and 1.2 to unlock public releases of X-Gold 608 basebands 04.26.08 through 05.13.04 and 06.15.00 (ultrasn0w 1.2 only), and XMM 6180 baseband 01.59.00)

iPhone 3G/3GS

 * 02.28.00 (Only with yellowsn0w)
 * 04.26.08
 * 05.11.07
 * 05.12.01
 * 05.13.04
 * 06.15.00.

iPhone 4

 * 01.59.00

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              ; handler_replace 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

Handler replace
RAM:00011600 ; =============== S U B R O U T I N E ======================================= RAM:00011600 RAM:00011600 RAM:00011600 handler_replace RAM:00011600                PUSH    {LR} RAM:00011602                LDR     R0, =0x40492FC0 ; where to save task_loop_jmp + task_loop RAM:00011604                ADR     R1, task_loop_jmp RAM:00011606                ADR     R2, task_loop_end RAM:00011608                SUBS    R2, R2, R1      ; size of task_loop + task_loop_jmp = 0x70 RAM:0001160A                LDR     R3, =0x2040882C ; memcpy RAM:0001160C                BLX     R3 RAM:0001160E                 LDR     R0, =0x40492C20 ; where to save task_creator_jmp + task_creator RAM:00011610                ADR     R1, task_creator_jmp RAM:00011612                ADR     R2, task_creator_end RAM:00011614                SUBS    R2, R2, R1      ; size of task_creator + task_creator_jmp = 0xA0 RAM:00011616                LDR     R3, =0x2040882C ; memcpy RAM:00011618                BLX     R3 RAM:0001161A                 LDR     R0, =0x40492C20 RAM:0001161C                BLX     R0              ; task_creator_jmp RAM:0001161E                POP     {PC} RAM:0001161E ; End of function handler_replace

Task creator (thanks Darkmen for the comments!)
RAM:40492C20 ; =============== S U B R O U T I N E ======================================= RAM:40492C20 RAM:40492C20 RAM:40492C20 task_creator_jmp RAM:40492C20                STMFD   SP!, {R1-R12,LR} RAM:40492C24                BLX     task_creator RAM:40492C28                LDMFD   SP!, {R1-R12,PC} RAM:40492C28 ; End of function task_creator_jmp RAM:40492C28 RAM:40492C2C RAM:40492C2C ; =============== S U B R O U T I N E ======================================= RAM:40492C2C RAM:40492C2C RAM:40492C2C task_creator                           ; CODE XREF: task_creator_jmp+4�p RAM:40492C2C                PUSH    {R4-R7,LR} RAM:40492C2E                LDR     R3, =0x401ED3B8 ; jumptable var RAM:40492C30                MOVLS   R4, 0x800 RAM:40492C34                SUB     SP, SP, #0x24 RAM:40492C36                STRH    R0, [R3]        ; task_creator_jmp addr RAM:40492C38                LDR     R5, =0x201493F0 ; malloc RAM:40492C3A                ADDS    R0, R4, #0      ; 0x800 RAM:40492C3C                ADDS    R7, R1, #0      ; R7 = resp_string RAM:40492C3E                BLX     R5              ; malloc(0x800) RAM:40492C40                ADDS    R6, R0, #0      ; R6 = addr returned from malloc RAM:40492C42                MOVS    R0, #0x98       ; sizeof(NU_TASK) RAM:40492C44                BLX     R5              ; malloc(sizeof(NU_TASK)) RAM:40492C46                MOVS    R2, #0 RAM:40492C48                MOVS    R3, #0x44 RAM:40492C4A                LDR     R1, =aDevteam1  ; char *name RAM:40492C4C                STR     R2, [R0,#0xC]   ; task.field=0 RAM:40492C4E                STR     R3, [SP,#0xC]   ; priority = 0x44 RAM:40492C50                MOVS    R3, #0xA RAM:40492C52                STR     R3, [SP,#0x14]  ; preempt = NU_PREEMPT RAM:40492C54                MOVS    R3, #0xC RAM:40492C56                STR     R2, [SP]        ; void *argv = 0 RAM:40492C58                STR     R4, [SP,#8]     ; stack_size = 0x800 RAM:40492C5A                STR     R2, [SP,#0x10]  ; time_slice = 0 RAM:40492C5C                STR     R3, [SP,#0x18]  ; auto_start = NU_START RAM:40492C5E                LDR     R2, =0x40492FC0 ; task_loop_jmp address RAM:40492C60                STR     R6, [SP,#4]     ; void *stack_address = malloc(0x800) RAM:40492C62                MOVS    R3, #0 RAM:40492C64                LDR     R4, =0x2043E5B4 ; NU_Create_Task RAM:40492C66                BLX     R4              ; status = NU_Create_Task RAM:40492C68                ADDS    R2, R0, #0      ; R2 = status (for the %d reference in sprintf) RAM:40492C6A                CMP     R0, #0          ; success = zero RAM:40492C6C                BNE     status_error RAM:40492C6E                LDR     R1, =aOk        ; "OK!" RAM:40492C70                ADDS    R0, R7, #0      ; resp_string RAM:40492C72                LDR     R3, =0x204B11F0 ; sprintf RAM:40492C74                BLX     R3              ; sprintf(resp_string, "OK!") RAM:40492C76                B       exit RAM:40492C78 ; --- RAM:40492C78 RAM:40492C78 status_error                           ; CODE XREF: task_creator+40�j RAM:40492C78                LDR     R1, =aErrorD    ; "ERROR %d" RAM:40492C7A                ADDS    R0, R7, #0      ; resp_string RAM:40492C7C                LDR     R3, =0x204B11F0 ; sprintf RAM:40492C7E                BLX     R3              ; sprintf(resp_string, "ERROR %d", status) RAM:40492C80 RAM:40492C80 exit                                   ; CODE XREF: task_creator+4A�j RAM:40492C80                ADD     SP, SP, #0x24   ; fixing stack RAM:40492C82                POP     {R4-R7,PC} RAM:40492C82 ; End of function task_creator

Unlock task loop (thanks Darkmen for the comments!)
RAM:00011630 ; =============== S U B R O U T I N E ======================================= RAM:00011630 RAM:00011630 RAM:00011630 task_loop_jmp RAM:00011630                STMFD   SP!, {R1-R12,LR} RAM:00011634                BLX     task_loop RAM:00011634 ; --- RAM:00011638                LDMFD   SP!, {R1-R12,PC} RAM:00011638 ; End of function task_loop_jmp RAM:00011638 RAM:0001163C RAM:0001163C ; =============== S U B R O U T I N E ======================================= RAM:0001163C RAM:0001163C RAM:0001163C task_loop RAM:0001163C                PUSH    {R4,R5,LR} RAM:0001163E                LDR     R5, =0x401E829C ; sec mailbox RAM:00011640                SUB     SP, SP, #0x14 RAM:00011642 RAM:00011642 loop                                   ; CODE XREF: task_loop+44�j RAM:00011642                LDR     R3, =0x2042FFD8 ; NU_Receive_From_Mailbox RAM:00011644                ADDS    R0, R5, #0      ; NU_MAILBOX *mailbox RAM:00011646                MOV     R1, SP          ; void *Message RAM:00011648                MOVS    R2, #0xFF       ; Timeout RAM:0001164A                BLX     R3              ; NU_Receive_From_Mailbox(sec_mailbox,SP,0xFF) RAM:0001164C                LDR     R3, [SP]        ; Message[0] RAM:0001164E                CMP     R3, #0xD        ; Message[0] = 0xD ? RAM:00011650                BNE     skip RAM:00011652                LDR     R1, [SP,#4]     ; Message[1] RAM:00011654                LDR     R3, =0x40301650 RAM:00011656                LDR     R2, [R1]        ; Message[1].field0 RAM:00011658                STR     R2, [R3]        ; sec_task_var1 = Message[1].field0 RAM:0001165A                ADDS    R3, #4          ; 0x40301654 RAM:0001165C                LDR     R2, [R1,#4]     ; Message[1].field1 RAM:0001165E                STR     R2, [R3]        ; sec_task_var2 = Message[1].field1 RAM:00011660                LDR     R2, [R1,#8]     ; Message[1].field2 RAM:00011662                LDR     R3, =0x100FF00 RAM:00011664                STR     R3, [R2]        ; Message[1].field2[0] = 0x100FF00 RAM:00011666                LDR     R3, =0x4020401 RAM:00011668                STR     R3, [R2,#4]     ; Message[1].field2[1] = 0x4020401 RAM:0001166A                LDR     R3, =0x4040403 RAM:0001166C                STR     R3, [R2,#8]     ; Message[1].field2[2] = 0x4040403 RAM:0001166E                MOVS    R3, #1 RAM:00011670                STR     R3, [R1,#0xC]   ; Message[1].field3 = 1 RAM:00011672                MOVS    R3, #0x20 ; ' ' RAM:00011674                STR     R3, [SP] ; Message[0] = 0x20 RAM:00011676 RAM:00011676 skip                                   ; CODE XREF: task_loop+14�j RAM:00011676                ADDS    R0, R5, #0      ; sec mailbox RAM:00011678                MOV     R1, SP          ; void *Message RAM:0001167A                MOVS    R2, #0xFF       ; timeout RAM:0001167C                LDR     R3, =0x20430040 RAM:0001167E                BLX     R3              ; NU_Send_To_Mailbox RAM:00011680                B       loop RAM:00011680 ; End of function task_loop RAM:00011680 RAM:00011680 ; ---

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

Planetbeing explains...
13:24:29  especially how does ultra/yellow sn0w work 13:24:40  are you overwriting instructions 13:24:48  or some values in memory to make it accept the sim? 13:24:48 Nah. 13:24:53 It's a task. 13:25:06 That just waits for securiy messages to go through the inbox. 13:25:13 planetbeing: btw, why isnt yellowsn0w/ultrasn0w not open-source anymore? like u posted an *oooold* version once

...

13:26:33 The only thing I do for ys/us is the loader bit. 13:26:39 so whats actually the loader stuff you've been talking about? 13:26:46 That uses the exploit to start MuscleNerd's payload. 13:27:21 ah 13:27:26  Well, you have a vulnerability. 13:27:30 And you want to load a large chunk of code. 13:27:39 And you don't have much room to wriggle in for your overflow 13:28:21 aah, makes sense 13:28:50 So the solution is a small loader that loads the rest of the code, and overcomes any restrictions there are on allowable characters. 13:28:55 francis: pm 13:28:59  yeah 13:29:10  planetbeing: the baseband is it like one process that runs there 13:29:19  or is it like a small os with process and stuff 13:29:19 Basically a good loader should turn a vulnerability into a reliable platform for the execution of arbitrary code, unrestricted by vulnerability-specific stuff. 13:29:37 Oh, it's a full-featured OS. 13:29:38 Nucleus. 13:29:51 http://www.mentor.com/products/embedded_software/nucleus_rtos/ 13:29:54  and when you execute an at command 13:30:06  does that start another process that is crashed then 13:30:21 Ideally, you don't crash anything. 13:30:21  or does it crash like the main baseband program 13:30:23 And we don't. 13:30:49   so am i understand it right 13:30:50 wait. is nucleus on the baseband already installed or do you actually inject it with ultrasn0w? 13:30:51 We load a bunch of code into certain memory locations, execute them, and then return safely back to the main command parser task. 13:31:00 Nucleus is what the baseband runs. 13:31:04 ah ok 13:31:29  I mean, even the bootrom is an OS. 13:31:36 With one task, but it still has a scheduler. =P 13:31:39  ah thats how you do it 13:31:42  heh 13:31:44  and about your payload 13:31:57  does it start a new process like using fork 13:32:03  or does it all the work in the exploited process 13:32:11 It uses Nucleus-specific calls that create the new task. 13:32:19 Well, the payload has to create a new task 13:32:22 I think they are documented on the wiki 13:32:25 To monitor for certain events. 13:32:47 Yeah, just read Darkmen's decompile. 13:33:00 us has the exact same payload as ys 13:33:08  Just different addresses for function calls and stuff. 13:33:19 And I had to rewrite the loader due to even tighter constraints. 13:33:28  thats cool, thanks for explaining 13:33:34 yup, thanks

From irc.saurik.com #iphone on sunday the 5th of july.

Source Code
The source code for yellowsn0w 0.9.1 (old version) was released along with yellowsn0w release.