Skip to content

Instantly share code, notes, and snippets.

@xerub
Created June 8, 2015 22:49
Show Gist options
  • Save xerub/2b873a4ca08820a4d4de to your computer and use it in GitHub Desktop.
Save xerub/2b873a4ca08820a4d4de to your computer and use it in GitHub Desktop.
blow, blow, ultrasn0w
/* ultrasn0w (D) xerub 2014
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the "do What The Fuck you want to Public License";
* either version 1 of the License, or whatever (the fuck) version you want.
*
* $ ios-clang -o ultrasn0w.o -Wno-variadic-macros -O2 -c ultrasn0w.c
* $ ios-clang -o ultrasn0w.dylib -shared ultrasn0w.o -lsubstrate -lATCommandStudioDynamic
*
* Inject into CommCenterClassic iPhone3,1 baseband 1.59.00
*/
#include <dlfcn.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/utsname.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
#include <mach/mach_init.h>
#include <mach/vm_map.h>
#include <mach-o/getsect.h>
#include <mach-o/dyld.h>
#define SPEED 115200
#define BUFSIZE (65536)
char *BasebandVersion(void);
int atprog(const char *cmds[], int num);
int my_open(const char *path, int flags, int mode);
int $XLockHandler(int a1, const char **a2, int a3, int a4);
int $InternalNotification(int a1, int a2, int a3, int a4, void *a5);
#define UDEBUG 1
#define OPTION_USE_ATCSD_XLOCK 1
#define OPTION_NO_TEMP_TIMEOUT 1 // XXX may be dangerous
#define OPTION_USE_OTHER_LOWFD 0
#define OPTION_ZAP_RESP_LENGTH 0
#define OPTION_PATCH_XCGEDPAGE 1
#define FW612 1
#define FW704 1
#define FW712 1
#define forever for (;;)
void MSHookFunction(vm_address_t addr, int (*f)(), void **pf);
#if UDEBUG
char *timestamp(void);
#define DBG(args...) do { fprintf(LogFile, args); fflush(LogFile); } while (0)
static const char *
noti(int a2)
{
static const char *names[] = {
/* 0 */ "kEventCallActive",
/* 1 */ "kEventCallInactive",
/* 2 */ "kEventRegistered",
/* 3 */ "kEventNotRegistered",
/* 4 */ "kEventNewNetwork",
/* 5 */ "kEventNewCell",
/* 6 */ "kEventRadioOff",
/* 7 */ "kEventRadioReset",
/* 8 */ "kEventRadioOn",
/* 9 */ "kEventRfDisabling",
/* 10 */ "kEventRfDisabled",
/* 11 */ "kEventSimDisabled",
/* 12 */ "kEventSimUnreadable",
/* 13 */ "kEventSimInitializing",
/* 14 */ "kEventSimReady",
/* 15 */ "kEventSimInitComplete",
/* 16 */ "kEventIccidAvailable",
/* 17 */ "kEventEnteringLowPower",
/* 18 */ "kEventExitingLowPower",
/* 19 */ "kEventSimRefresh",
/* 20 */ "kEventSimFsRefresh",
/* 21 */ "kEventDumpState",
/* 22 */ "kEventManualSelectionDisabled",
/* 23 */ "kEventHomePlmnUpdated",
/* 24 */ "kEventPinBlocked",
/* 25 */ "kEventPukBlocked",
/* 26 */ "kEventNewOutgoingCallId",
/* 27 */ "kEventSimPinEntryRequest",
/* 28 */ "kEventSimPukEntryRequest",
/* 29 */ "kEventSimPinAccessResponse",
/* 30 */ "kEventSimPukAccessResponse",
/* 31 */ "kEventEnteringBrickState",
/* 32 */ "kEventExitingBrickState",
/* 33 */ "kEventDataAttached",
/* 34 */ "kEventDataNotAttached",
/* 35 */ "kEventQuerySimStatus",
/* 36 */ "kEventDataMode",
/* 37 */ "kEventRadioMaxTxPower",
/* 38 */ "kEventPdpContextActivated",
/* 39 */ "kEventPdpContextDeactivated",
/* 40 */ "kEventRAT",
/* 41 */ "kEventPhoneNumberAvailable",
/* 42 */ "kEventClearSimPIN",
/* 43 */ "kEventSimType",
/* 44 */ "kEventXSMSReady",
/* 45 */ "kEventCallingLineIdRestrictionValueChanged",
/* 46 */ "kEventOtaspCommitted",
/* 47 */ "kEventECBMChanged",
/* 48 */ "kEventEmergencyNumbersAvailbale",
/* 49 */ "kEventNewCallinECBM",
/* 50 */ "kEventECBMError",
/* 51 */ "kEventFileTransferSuccessful",
/* 52 */ "kEventFileTransferError",
/* 53 */ "kEventSIMRefreshReceived",
/* 54 */ "kEventServiceProvisionStateChanged",
/* 55 */ "kEventActiveCallInSettingsModel",
/* 56 */ "kEventCellularDataStatusAvailable"
};
int n = sizeof(names) / sizeof(names[0]);
if (a2 >= 0 && a2 < n) {
return names[a2];
}
return "???";
}
#else /* !UDEBUG */
#define DBG(args...)
#define noti(x) ""
#endif /* !UDEBUG */
FILE *LogFile;
vm_address_t XLockHandler;
vm_address_t InternalNotification;
int (*_XLockHandler)(int a1, const char **a2, int a3, int a4);
int (*_InternalNotification)(int a1, int a2, int a3, int a4, void *a5);
int (*_orig_open)(const char *pathname, int flags, mode_t mode);
int fw;
int lowFD;
char readbuf[BUFSIZE];
struct termios term;
const char *unlock_strings[4] = {
"at+xapp=\"...................................."
"\x88\x6a\xff\xed\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
"\x2d\x7a\x01\x60\x22\x3b\x22\x58\x58\x34\x34\x34\x34\x35\x35\x35"
"\x35\x36\x36\x36\x36\x37\x37\x37\x37\xf3\xa0\x14\x60\x55\x55\x55"
"\x55\x07\x48\x80\x47\xd0\x1f\xff\xff\xf1\xa0\x14\x60\x55\x55\x55"
"\x55\x07\x1c\x0f\xbc\xd4\x1f\xff\xff\xf1\xa0\x14\x60\x55\x55\x55"
"\x55\xd2\x18\x07\x4b\xd8\x1f\xff\xff\xf1\xa0\x14\x60\x55\x55\x55"
"\x55\x98\x47\x38\x1c\xdc\x1f\xff\xff\xf1\xa0\x14\x60\x55\x55\x55"
"\x55\x04\x49\x88\x47\xe0\x1f\xff\xff\xf1\xa0\x14\x60\x55\x55\x55"
"\x55\x01\x49\x8d\x46\xe4\x1f\xff\xff\xf1\xa0\x14\x60\x55\x55\x55"
"\x55\x48\x1a\xf0\xbd\xe8\x1f\xff\xff\xf1\xa0\x14\x60\x55\x55\x55"
"\x55\x6c\x3c\x88\x72\xec\x1f\xff\xff\xf1\xa0\x14\x60\x55\x55\x55"
"\x55\x5c\x13\x18\x60\xf0\x1f\xff\xff\xf1\xa0\x14\x60\x55\x55\x55"
"\x55\x6c\x13\x18\x60\xf4\x1f\xff\xff\xf1\xa0\x14\x60\x55\x55\x55"
"\x55\xfc\xd9\x1f\x60\xf8\x1f\xff\xff\xf1\xa0\x14\x60\x33\x33\x33"
"\x33\x34\x34\x34\x34\x35\x35\x35\x35\xd1\x1f\xff\xff\xd0\x04\xff"
"\xff\xbc\xa7\x87\x60\x59\x01\x01\x01\xff\xfe\xfe\xfe\x04\xf0\x1f"
"\xe5\x34\x63\x73\x40\x0f\x48\x80\x38\x80\x38\x0f\x4a\x10\x60\xe4"
"\x19\x0e\x48\x80\x47\x07\x1c\xaa\x19\x20\x25\x02\x35\x20\x78\xa8"
"\x42\x09\xd0\xc0\x46\xff\x28\x02\xd1\x01\x34\x20\x78\x01\x30\x10"
"\x70\x01\x34\x01\x32\xf2\xe7\x38\x1c\x05\x49\x88\x47\x48\x1a\x6a"
"\x46\x12\x68\x10\x47\x1f\x01\xfa\x60\x80\x12\x70\x60\x5c\x13\x18"
"\x60\x6c\x13\x18\x60\"",
"at+xapp=\"...................................."
"\xdb\xa7\x88\x61\x01\x01\xfb\x61\xff\xfe\xfe\xfe\xff\xfe\xfe\xfe"
"\xd9\x04\xff\xff\x5d\x6e\x18\x60\x22\x3b\x22\xff\xff\xff\xff\x10"
"\xff\xff\x45\xff\xfe\x10\xbd\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5"
"\x05\x40\x2a\x80\x1c\xff\xff\x0c\xff\xff\x78\x47\xff\xff\x1c\x04"
"\xf0\x1f\xe5\x1d\x40\x2a\x80\x80\xff\xff\xff\x21\xff\xff\x04\xf0"
"\x1f\xe5\xff\xff\x6f\x73\x40\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5"
"\xa1\x40\x2a\x80\x04\xf0\x1f\xe5\xf8\x6e\x73\x40\xf7\xff\xfe\xff"
"\xfe\xea\xf2\xe7\xa4\xff\xff\xa6\xff\xff\x04\xf0\x1f\xe5\xff\x07"
"\x6f\x73\x40\x04\xf0\x1f\xe5\x10\x6f\x73\x40\x04\xf0\x1f\xe5\x18"
"\x6f\x73\x40\x04\xf0\x1f\xe5\x20\x6f\x73\x40\x04\xf0\x1f\xe5\x28"
"\x6f\x73\x40\x04\xf0\x1f\xe5\x30\x6f\x73\x40\x04\xf0\x1f\xe5\x38"
"\x6f\x73\x40\x04\xf0\x1f\xe5\x40\x6f\x73\x40\x04\xf0\x1f\xe5\x48"
"\x6f\x73\x40\x04\xf0\x1f\xe5\x50\x6f\x73\x40\x04\xf0\x1f\xe5\x58"
"\x6f\x73\x40\x04\xf0\x1f\xe5\x60\x6f\x73\x40\x04\xf0\x1f\xe5\x68"
"\x6f\x73\x40\x04\xf0\x1f\xe5\x70\x6f\x73\x40\x04\xf0\x1f\xe5\x78"
"\x6f\x73\x40\x04\xf0\x1f\xe5\x80\x6f\x73\x40\x04\xf0\x1f\xe5\x88"
"\x6f\x73\x40\x04\xf0\x1f\xe5\x90\x6f\x73\x40\x04\xf0\x1f\xe5\x98"
"\x6f\x73\x40\x04\xf0\x1f\xe5\xa0\x6f\x73\x40\x04\xff\xff\xff\xff"
"\xea\x02\xe0\x4c\x01\x02\xff\xff\x0a\xe0\x50\x01\x20\xff\xff\x78"
"\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x49\x41\x2a\x80\x04\xf0\x1f\xe5"
"\xa8\x6f\x73\x40\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\xb1\x6f\x73"
"\x40\x44\x03\x0c\xff\xff\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x45"
"\x43\x2a\x80\x54\x03\x0c\xff\xff\x78\x47\xff\xff\x1c\x04\xf0\x1f"
"\xe5\xb9\x71\x73\x40\x20\x04\x0c\xff\xff\x78\x47\xff\xff\x1c\x04"
"\xf0\x1f\xe5\x21\x44\x2a\x80\xa4\x04\x0c\xff\xff\x78\x47\xff\xff"
"\x1c\x04\xf0\x1f\xe5\x09\x73\x73\x40\xb4\x04\x0c\xff\xff\x78\x47"
"\xff\xff\x1c\x04\xf0\x1f\xe5\xb5\x44\x2a\x80\x3c\x05\x0c\xff\xff"
"\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x3d\x45\x2a\x80\x5c\x05\x0e"
"\xff\xff\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x6d\x45\x2a\x80\xff"
"\x07\xe0\x6c\x05\x02\xff\xff\xf6\xe7\x70\x05\x18\xff\xff\x78\x47"
"\xff\xff\x1c\x04\xf0\x1f\xe5\x71\x45\x2a\x80\x78\x47\xff\xff\x1c"
"\x04\xf0\x1f\xe5\x69\x45\x2a\x80\xf0\x06\x0c\xff\xff\x78\x47\xff"
"\xff\x1c\x04\xf0\x1f\xe5\x55\x75\x73\x40\x34\x07\x0c\xff\xff\x78"
"\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x35\x47\x2a\x80\x5c\x07\x0c\xff"
"\xff\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x5d\x47\x2a\x80\xc0\x07"
"\x10\xff\xff\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\xcd\x47\x2a\x80"
"\xff\xff\x20\x70\x47\xd4\x07\x0c\xff\xff\x78\x47\xff\xff\x1c\x04"
"\xf0\x1f\xe5\x39\x76\x73\x40\x88\xff\x07\x0c\xff\xff\x78\x47\xff"
"\xff\x1c\x04\xf0\x1f\xe5\xed\x76\x73\x40\xcc\xff\x07\x0c\xff\xff"
"\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\xcd\x48\x2a\x80\xec\xff\x07"
"\x0c\xff\xff\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x51\x77\x73\x40"
"\xb4\x09\x0c\xff\xff\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x19\x78"
"\x73\x40\xb4\x0a\x0c\xff\xff\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5"
"\xb5\x4a\x2a\x80\x18\x0b\x0c\xff\xff\x78\x47\xff\xff\x1c\x04\xf0"
"\x1f\xe5\x7d\x79\x73\x40\x6c\x0b\x18\xff\xff\x78\x47\xff\xff\x1c"
"\x04\xf0\x1f\xe5\x6d\x4b\x2a\x80\x78\x47\xff\xff\x1c\x04\xf0\x1f"
"\xe5\x79\x4b\x2a\x80\xe4\x0b\x0c\xff\xff\x78\x47\xff\xff\x1c\x04"
"\xf0\x1f\xe5\xe5\x4b\x2a\x80\xbc\xff\x0c\x18\xff\xff\x78\x47\xff"
"\xff\x1c\x04\xf0\x1f\xe5\x21\x7c\x73\x40\x78\x47\xff\xff\x1c\x04"
"\xf0\x1f\xe5\x2d\x7c\x73\x40\x64\x0e\x0c\xff\xff\x78\x47\xff\xff"
"\x1c\x04\xf0\x1f\xe5\xc9\x7c\x73\x40\xdc\x0e\x0c\xff\xff\x78\x47"
"\xff\xff\x1c\x04\xf0\x1f\xe5\xdd\x4e\x2a\x80\xec\x0e\x0c\xff\xff"
"\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\xfb\x4e\x2a\x80\xfa\x0e\x02"
"\xff\xff\xf7\xe7\x04\x0f\x0e\xff\xff\x78\x47\xff\xff\x1c\x04\xf0"
"\x1f\xe5\x75\x7d\x73\x40\xf8\xe7\x18\x0f\x0c\xff\xff\x78\x47\xff"
"\xff\x1c\x04\xf0\x1f\xe5\x19\x4f\x2a\x80\x2e\x0f\x0e\xff\xff\xff"
"\xfe\xe7\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x2f\x4f\x2a\x80\x4c"
"\x0f\x0c\xff\xff\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x4d\x4f\"",
"at+xapp=\"...................................."
"\xdb\xa7\x88\x61\x27\x04\xfb\x61\xff\xfe\xfe\xfe\xff\xfe\xfe\xfe"
"\xd9\x04\xff\xff\x5d\x6e\x18\x60\x22\x3b\x22\x2a\x80\x6a\x0f\x0e"
"\xff\xff\xff\xfe\xe7\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x6b\x4f"
"\x2a\x80\x7c\x0f\x0e\xff\xff\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5"
"\x89\x4f\x2a\x80\xf8\xe7\x92\x0f\x0e\xff\xff\xff\xfe\xe7\x78\x47"
"\xff\xff\x1c\x04\xf0\x1f\xe5\x93\x4f\x2a\x80\xa4\x0f\x24\xff\xff"
"\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\xff\xfe\x4f\x2a\x80\x78\x47"
"\xff\xff\x1c\x04\xf0\x1f\xe5\xb1\x4f\x2a\x80\x78\x47\xff\xff\x1c"
"\x04\xf0\x1f\xe5\x21\x7e\x73\x40\xce\x0f\x0e\xff\xff\xff\xfe\xe7"
"\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\xcf\x4f\x2a\x80\xe6\x0f\x0e"
"\xff\xff\xff\xfe\xe7\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\xe7\x4f"
"\x2a\x80\xfe\x0f\x02\xff\xff\xd1\xe7\xff\xff\xff\xff\xff\xff\xff"
"\xff\"",
"at+xapp=\"...................................."
"\xdb\xa7\x88\x61\x9b\x0a\x01\x01\xff\xfe\xfd\xfe\xff\xfe\xfe\xfe"
"\xd9\x04\xff\xff\xa9\x09\xff\xff\x22\x3b\x22\xff\xff\x1c\x78\x47"
"\xff\xff\x1c\x04\xf0\x1f\xe5\xff\xfe\x67\x73\x40\xf0\xb4\xff\xff"
"\xf0\x59\xf8\x58\x48\x58\x49\xff\xff\xf0\x64\xf8\x5d\x4c\x5b\x4d"
"\x60\x4e\xff\xff\x2e\x09\xd0\x60\x19\xff\xff\xf0\x86\xf8\x57\x49"
"\x21\x43\x01\x60\x54\x48\x24\x18\x36\x1a\xf3\xe7\x5b\x4c\x20\x1c"
"\xff\xff\xf0\x7b\xf8\xff\xff\x68\x21\x1c\xff\xff\xf0\x7c\xf8\x21"
"\x1c\x1f\x31\x01\x60\x40\xa3\x98\x47\x20\x1c\x53\x49\x09\xff\x0c"
"\x09\x05\x1f\x31\x49\x4b\x47\x4d\xff\xff\x2b\x04\xd0\x01\x60\x5b"
"\x1b\x49\x19\x04\x30\xf8\xe7\x4d\x48\xff\xff\xf0\x61\xf8\x09\x34"
"\x04\x60\x20\x1c\x4a\x49\xff\xff\xf0\x60\xf8\x3c\x49\x1f\x31\x01"
"\x60\x32\xa3\x98\x47\x46\x48\x3f\x49\x09\x18\xff\xff\xf0\x27\xf8"
"\x46\x4c\x47\x4d\x36\x4e\x28\x88\x6a\x88\x17\x1c\xff\xff\x2a\x05"
"\xd0\x04\x35\x29\x1c\x80\x19\xa0\x47\xed\x19\xf4\xe7\x44\x48\x41"
"\xa1\x0c\xff\x21\xa0\x47\xff\xff\xf0\x0e\xf8\xf0\xbc\xff\xff\x20"
"\x3a\x4b\x18\x47\xff\xff\xb5\x26\x48\x80\x47\x27\xa1\xff\x07\x60"
"\xc0\x21\xff\x07\x43\x24\x49\x88\x47\xff\xff\xbd\xff\xff\xb5\x23"
"\x48\x21\x49\x88\x47\xff\xff\xbd\xf0\xb5\x81\xb0\x05\x1c\x0e\x1c"
"\x21\x4f\x3f\x68\x1f\x4c\x24\x68\xff\xff\x20\xff\xff\x90\xb8\x42"
"\x0b\xd0\xe0\x68\x21\x69\x2a\x1c\x33\x1c\xff\xff\xf0\xff\x07\xf8"
"\x8c\x20\x24\x58\xff\xff\x98\x01\x30\xff\xff\x90\xf1\xe7\x01\xb0"
"\xf0\xbd\x30\xb5\x12\x0b\x88\x42\x0a\xd2\x04\x68\x24\x0b\x94\x42"
"\x04\xd1\x04\x68\x24\x05\x24\xff\x0c\xe4\x18\x04\x60\x04\x30\xf2"
"\xe7\x30\xbd\x02\xff\x0c\x92\xff\xff\x11\x4b\xd0\x18\x70\x47\x80"
"\x0a\x80\x02\x09\x0b\xff\xfe\x23\x19\x40\x89\xff\xff\xff\x07\x43"
"\x70\x47\x17\x0f\xff\x07\xee\x16\x0f\xff\x07\xee\xff\x14\x0f\xff"
"\x07\xee\x1e\xff\xfe\x2f\xe1\x18\xb0\x38\x60\x6c\x13\x18\x60\xff"
"\xfe\xff\xfe\xff\xfe\xff\xfe\x18\xff\x21\xff\xfe\xff\xfe\x1c\xff"
"\x21\xff\xfe\xff\xfe\xff\xff\x10\xff\xfe\xff\xfe\x64\x6e\x73\x40"
"\xff\xff\x10\xff\xff\xff\xff\xff\xff\xff\xff\x09\xff\xff\xff\xff"
"\xff\xff\x10\xff\xff\x0e\x04\xff\x07\xff\xff\xff\xff\xff\xff\xff"
"\xff\x20\xff\xff\xff\xff\xff\xff\x60\x54\x63\x48\x60\xb0\xec\x83"
"\x60\x10\x2a\xff\xfe\xff\xfe\xff\xff\xff\xff\xff\xff\x10\xff\xff"
"\x40\x2a\x60\xff\xff\xe0\xf9\x60\x5d\x6e\x18\x60\xfc\xd9\x1f\x60"
"\xff\xff\xff\xff\xfa\x60\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\xdd"
"\x6d\x73\x40\x78\x0f\xff\xfe\xff\xfe\""
};
const char *activation_ticket[6] = {
"at+xlck=0",
"at+xlck=1,1,\"000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000\"",
"at+xlck=1,2,\"000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000\"",
"at+xlck=1,3,\"000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000\"",
"at+xlck=1,4,\"000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000\"",
"at+xlck=2"
};
int IsCompatible = -1;
pthread_mutex_t at_mutex = PTHREAD_MUTEX_INITIALIZER;
unsigned slide = 0;
int debug = 1;
kern_return_t
writeWord(vm_address_t addr, uint16_t val, int exec)
{
vm_prot_t new_protection;
unsigned pagesize = getpagesize();
mach_port_t port = mach_task_self();
DBG("%s writeWord %x at %x/%x\n", timestamp(), val, addr - slide, addr);
if (vm_protect(port, addr / pagesize * pagesize, pagesize, 0, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY)) {
return 1;
}
*(uint16_t *)addr = val;
if (exec) {
new_protection = VM_PROT_READ | VM_PROT_EXECUTE;
} else {
new_protection = VM_PROT_READ;
}
if (vm_protect(port, addr / pagesize * pagesize, pagesize, 0, new_protection)) {
return 1;
}
DBG("%s writeWord ok: %x\n", timestamp(), *(uint16_t *)addr);
return 0;
}
vm_address_t
FindLastThumbFunction(vm_address_t addr)
{
uint16_t *ptr, *p;
unsigned int size;
if (slide) {
ptr = (uint16_t *)(getsectdata("__TEXT", "__text", (unsigned long *)&size) + slide);
} else {
ptr = (uint16_t *)getsectdatafromheader((struct mach_header *)0x1000, "__TEXT", "__text", &size);
}
p = (uint16_t *)(addr & ~3);
while (--p >= (uint16_t *)ptr) {
if ((p[0] & 0xFF00) == 0xB500 && (p[-1] & 0xF000) != 0xF000) {
return (vm_address_t)p + 1;
}
}
return 0;
}
vm_address_t
FindReference(vm_address_t addr)
{
char *ptr, *end;
unsigned int size;
if (slide) {
ptr = getsectdata("__TEXT", "__text", (unsigned long *)&size) + slide;
} else {
ptr = getsectdatafromheader((struct mach_header *)0x1000, "__TEXT", "__text", &size);
}
end = ptr + size - 4;
if (!addr) {
return 0;
}
for (; ptr < end; ptr++) {
if (!memcmp(ptr, &addr, 4)) {
return (vm_address_t)ptr;
}
}
if (addr == 0xAFBB8) {
return 0x55230;
}
if (addr == 0xA8E3C) {
return 0x2AE8C;
}
#define SLIDE(a, x) if (addr == slide + (a)) return (x) + slide
switch (fw) {
case 431:
SLIDE(0xF47AC, 0x6039C);
SLIDE(0xED6C0, 0x34114);
SLIDE(0xF02EC, 0x458B4);
break;
case 432:
SLIDE(0xF47AC, 0x60370);
SLIDE(0xED6C0, 0x340E8);
SLIDE(0xF02EC, 0x45888);
break;
case 433:
SLIDE(0xF4738, 0x6030C);
SLIDE(0xED64C, 0x34110);
SLIDE(0xF0278, 0x45824);
break;
case 500:
SLIDE(0x124DD5, 0x680B4);
SLIDE(0x11CEC9, 0x35704);
SLIDE(0x11FEA1, 0x4BB24);
break;
case 501:
SLIDE(0x124DD0, 0x67B54);
SLIDE(0x11CE6C, 0x34FA8);
SLIDE(0x11FE60, 0x4B504);
break;
case 51:
SLIDE(0x117DC8, 0x6B754);
SLIDE(0x10FCB0, 0x38820);
SLIDE(0x112CBD, 0x4EF0C);
break;
case 511:
SLIDE(0x117BF8, 0x6B2C0);
SLIDE(0x10FAE0, 0x3838C);
SLIDE(0x112AED, 0x4EA78);
break;
#if FW612
case 612:
SLIDE(0x1D0834, 0xAB308);
SLIDE(0x1C813F, 0x56B1A);
SLIDE(0x1CB735, 0x7DABC);
#if OPTION_NO_TEMP_TIMEOUT
SLIDE(0x1CE4E9, 0xA39DE);
#endif
break;
#endif
#if FW704
case 704:
SLIDE(0x2E917E, 0x12C0AE);
SLIDE(0x2DF714, 0x8C852);
SLIDE(0x2E3373, 0xBF360);
#if OPTION_NO_TEMP_TIMEOUT
SLIDE(0x2E6D99, 0x122A4E);
#endif
break;
#endif
#if FW712
case 712:
SLIDE(0x2FB767, 0x13216E);
SLIDE(0x2F1CA5, 0x808D6);
SLIDE(0x2F5938, 0xB49F8);
#if OPTION_NO_TEMP_TIMEOUT
SLIDE(0x2F9382, 0x128B7E);
#endif
break;
#endif
}
#undef SLIDE
return 0;
}
vm_address_t
FindString(const char *str)
{
char *ptr, *end;
unsigned int size;
if (slide) {
ptr = getsectdata("__TEXT", "__cstring", (unsigned long *)&size) + slide;
} else {
ptr = getsectdatafromheader((struct mach_header *)0x1000, "__TEXT", "__cstring", &size);
}
for (end = ptr + size - strlen(str); ptr < end; ptr++) {
if (!strcmp(ptr, str)) {
return (vm_address_t)ptr;
}
}
return 0;
}
char *
FindStringN(const char *str, size_t n)
{
char *ptr;
char *end;
unsigned int size;
if (slide) {
ptr = getsectdata("__TEXT", "__cstring", (unsigned long *)&size) + slide;
} else {
ptr = getsectdatafromheader((struct mach_header *)0x1000, "__TEXT", "__cstring", &size);
}
for (end = ptr + size - strlen(str); ptr < end; ptr++) {
if (!strncmp(ptr, str, n)) {
return ptr;
}
}
return NULL;
}
char *
timestamp(void)
{
static char buf[32];
time_t t = time(NULL);
#if UDEBUG
int len = sprintf(buf, "%u", getpid());
buf[len++] = ' ';
ctime_r(&t, buf + len);
buf[len + 24] = '\0';
#else
ctime_r(&t, buf);
buf[24] = '\0';
#endif
return buf;
}
void __attribute__((constructor))
Start(void)
{
struct utsname buf;
vm_address_t addr;
memset(&buf, 0, sizeof(buf));
uname(&buf);
if (strcmp("iPhone3,1", buf.machine)) {
dlopen("/usr/share/ultrasn0w/ultrasn0w-xgold608.dylib", RTLD_LAZY | RTLD_GLOBAL);
return;
}
LogFile = fopen("/var/wireless/Library/Logs/ultrasn0w-dylib.log", "w");
DBG("==================================================================== %u\n", getpid());
fprintf(LogFile, "%s ultrasn0w loaded via CommCenter\n", timestamp());
fflush(LogFile);
slide = _dyld_get_image_vmaddr_slide(0);
addr = FindString("+xsimstate=1") - slide;
if (FindStringN("Mar 18 2011", 11)) {
fw = 431;
}
if (FindStringN("Apr 4 2011", 11)) {
fw = 432;
}
if (FindStringN("Apr 28 2011", 11)) {
fw = 433;
}
if (addr == 0x11CF51) {
fw = 500;
} else if (addr == 0x11CEF4) {
fw = 501;
} else if (addr == 0x10FD38) {
fw = 51;
} else if (addr == 0x10FB68) {
fw = 511;
#if FW612
} else if (addr == 0x1C81C7) {
fw = 612;
#endif
#if FW704
} else if (addr == 0x2DF79C) {
fw = 704;
#endif
#if FW712
} else if (addr == 0x2F1D2D) {
fw = 712;
#endif
}
DBG("%s fw = %d\n", timestamp(), fw);
addr = FindReference(FindString("+xcgedpage=0,1"));
if (addr) {
addr = FindLastThumbFunction(addr);
DBG("%s xcged = %x/%x\n", timestamp(), addr - slide, addr);
if (*(uint16_t *)(addr + 15) == 0xB183) {
writeWord(addr + 15, 0xE010, 1);
} else if (*(uint16_t *)(addr + 23) == 0xD017) {
writeWord(addr + 23, 0xE017, 1);
#if OPTION_PATCH_XCGEDPAGE
#if FW612
} else if (*(uint16_t *)(addr + 23) == 0xD018) {
writeWord(addr + 23, 0xE018, 1);
#endif
#if FW704 || FW712
} else if (*(uint16_t *)(addr + 19) == 0xB1C1) {
writeWord(addr + 19, 0xE018, 1);
#endif
#endif /* OPTION_PATCH_XCGEDPAGE */
}
}
#if OPTION_NO_TEMP_TIMEOUT && (FW612 || FW704 || FW712)
addr = FindReference(FindString("+xdrv=5,16,%d"));
if (addr) {
addr = FindLastThumbFunction(addr);
DBG("%s xdrv5 = %x/%x\n", timestamp(), addr - slide, addr);
if (0) {
#if FW612
} else if (*(uint16_t *)(addr + 19) == 0x2D01) {
writeWord(addr + 19, 0x2DFF, 1);
#endif
#if FW704 || FW712
} else if (*(uint16_t *)(addr + 23) == 0x2D01) {
writeWord(addr + 23, 0x2DFF, 1);
#endif
}
}
#endif /* OPTION_NO_TEMP_TIMEOUT */
addr = FindReference(FindString("Sending internal notification %s (%d) params={%d, %d, %p}\n"));
if (addr) {
InternalNotification = FindLastThumbFunction(addr);
DBG("%s InternalNotification = %x/%x\n", timestamp(), InternalNotification - slide, InternalNotification);
addr = FindReference(FindString("activation ticket accepted... drive thru\n"));
if (addr) {
XLockHandler = FindLastThumbFunction(addr);
DBG("%s XLockHandler = %x/%x\n", timestamp(), XLockHandler - slide, XLockHandler);
MSHookFunction(InternalNotification, $InternalNotification, (void **)&_InternalNotification);
MSHookFunction(XLockHandler, $XLockHandler, (void **)&_XLockHandler);
MSHookFunction((vm_address_t)open, my_open, (void **)&_orig_open);
fprintf(LogFile, "%s ultrasn0w hooked\n", timestamp());
fflush(LogFile);
}
}
}
int
my_open(const char *path, int flags, int mode)
{
int fd = _orig_open(path, flags, mode);
if (!strcmp(path, "/dev/dlci.spi-baseband.low")) {
DBG("%s my_open(%s, 0x%x, 0%o)\n", timestamp(), path, flags, mode);
if (fw == 431
#if OPTION_USE_OTHER_LOWFD
|| fw == 612 // XXX 612?
|| fw == 704 // XXX 704?
|| fw == 712 // XXX 712?
#endif
) {
lowFD = _orig_open("/dev/dlci.spi-baseband.extra_0", flags, 0); // XXX mode?
} else {
lowFD = fd;
}
DBG("%s lowFD = %d\n", timestamp(), lowFD);
}
return fd;
}
#if OPTION_USE_ATCSD_XLOCK
bool _ZNK10ATResponse14isFieldPresentEiib(void *this, int index, int, bool);
void _ZNK10ATResponse22getStringFieldInternalENS_11FieldFormatEiii(void *out, void *this, int/*format?*/, int index, int, int);
int _ZNK10ATResponse11getIntFieldEiii(void *this, int index, int, int base);
#endif
int
$XLockHandler(int a1, const char **a2, int a3, int a4)
{
pthread_mutex_lock(&at_mutex);
DBG("%s XLockHandler= %p %p %p %p %p %p\n", timestamp(), a2[0], a2[1], a2[2], a2[3], a2[4], a2[5]);
{
#if OPTION_USE_ATCSD_XLOCK
bool present = _ZNK10ATResponse14isFieldPresentEiib(a2, 0, 0, false);
DBG("%s XLockHandler: isFieldPresent: %d\n", timestamp(), present);
if (present) {
int i;
for (i = 0; _ZNK10ATResponse14isFieldPresentEiib(a2, i + 2, 0, false); i += 3) {
char out[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
_ZNK10ATResponse22getStringFieldInternalENS_11FieldFormatEiii(out, a2, 0, i, 0, 0);
if (out) {
int v7 = _ZNK10ATResponse11getIntFieldEiii(a2, i + 1, 0, 10);
int v4 = _ZNK10ATResponse11getIntFieldEiii(a2, i + 2, 0, 10);
if (out[0] == 4 && out[1] == 'P' && out[2] == 'N' && out[3] == '\0') {
DBG("%s XLockHandler: PN %d %d\n", timestamp(), v7, v4);
if (IsCompatible && v7 == 1 && v4 == 1) {
DBG("%s XLockHandler: activation_ticket\n", timestamp());
write(lowFD, "at+xpow=1\r", 10);
atprog(activation_ticket, 6);
write(lowFD, "at+xpow=0\r", 10);
}
}
}
}
}
#else /* !OPTION_USE_ATCSD_XLOCK */
const char *const *p2 = a2;
#if 1 /* XXX higher FWs need this? */
if (p2[0] < (char *)0x1000 || p2[0] >= (char *)0x40000000) {
p2 += 2;
if (p2[0] < (char *)0x1000 || p2[0] >= (char *)0x40000000) {
p2 += 2;
if (p2[0] < (char *)0x1000 || p2[0] >= (char *)0x40000000) {
goto done;
}
}
}
#endif
DBG("%s XLockHandler: %s\n", timestamp(), p2[0]);
if (IsCompatible == 1 && strstr(p2[0], "+XLOCK: \"PN\",1,1")) {
DBG("%s XLockHandler: activation_ticket\n", timestamp());
write(lowFD, "at+xpow=1\r", 10);
atprog(activation_ticket, 6);
write(lowFD, "at+xpow=0\r", 10);
}
done:;
#endif /* !OPTION_USE_ATCSD_XLOCK */
}
pthread_mutex_unlock(&at_mutex);
return _XLockHandler(a1, a2, a3, a4);
}
int
CheckCompatibility(void)
{
const char *version;
int i = 0;
int retries = (fw >= 500) ? 2 : 5;
forever {
version = BasebandVersion();
if (version && *version) {
break;
}
if (++i >= retries) {
if (version && *version) {
break;
}
if (fw >= 500) {
fprintf(LogFile, "%s Unable to query baseband version...will assume it's compatible\n", timestamp());
return 1;
}
fprintf(LogFile, "%s Unable to query baseband version...will assume it's NOT compatible\n", timestamp());
return 0;
}
}
if (!strcmp(version, "01.59.00")) {
return 1;
}
fprintf(LogFile, "%s ERROR! %s works only for baseband \"%s\", but this baseband is \"%s\"\n", "ultrasn0w", timestamp(), "01.59.00", version);
return 0;
}
int
$InternalNotification(int a1, int a2, int a3, int a4, void *a5)
{
pthread_mutex_lock(&at_mutex);
DBG("%s InternalNotification(%d:%s, %d, %d, %p)\n", timestamp(), a2, noti(a2), a3, a4, a5);
if (a2 == 7) {
write(lowFD, "at+xpow=1\r", 10);
fprintf(LogFile, "%s Baseband reset!\n", timestamp());
fflush(LogFile);
if (IsCompatible == -1) {
IsCompatible = CheckCompatibility();
}
if (IsCompatible == 1) {
fprintf(LogFile, "%s Unlocking!\n", timestamp());
fflush(LogFile);
atprog(unlock_strings, 4);
fprintf(LogFile, "%s Unlocking commands sent!\n", timestamp());
fflush(LogFile);
}
write(lowFD, "at+xpow=0\r", 10);
}
pthread_mutex_unlock(&at_mutex);
return _InternalNotification(a1, a2, a3, a4, a5);
}
int
InitConn(speed_t speed)
{
int handshake = TIOCM_DSR | TIOCM_CTS | TIOCM_RTS | TIOCM_DTR;
int blahnull = 0;
int fd = open("/dev/tty.debug", O_NOCTTY | O_RDWR);
if (fd == -1) {
perror("open");
exit(1);
}
ioctl(fd, TIOCEXCL);
fcntl(fd, F_SETFL, 0);
tcgetattr(fd, (struct termios *)&term);
ioctl(fd, _IOW('T', 10, int), &blahnull);
cfsetspeed((struct termios *)&term, speed);
cfmakeraw((struct termios *)&term);
term.c_cc[VTIME] = 5;
term.c_iflag = (term.c_iflag & ~(ICRNL | IXON | IXOFF | IXANY | INPCK | ISTRIP | IGNBRK | BRKINT | IGNPAR)) | IGNPAR | IGNBRK;
term.c_cc[VMIN] = 0;
term.c_oflag &= ~OPOST;
term.c_cflag = (term.c_cflag & ~PARENB) | CS8;
term.c_lflag &= ~(IEXTEN | ICANON | ISIG | ECHO);
tcsetattr(fd, TCSANOW, &term);
ioctl(fd, TIOCSDTR);
ioctl(fd, TIOCCDTR);
ioctl(fd, TIOCMSET, &handshake);
return fd;
}
int
ReadResp(int fd, unsigned int timeout_sec, unsigned int timeout_micro)
{
struct timeval timeout;
struct timeval *to;
fd_set readfds;
int nfds;
int len = 0;
nfds = fd + 1;
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
timeout.tv_sec = timeout_sec;
timeout.tv_usec = timeout_micro;
if (timeout.tv_sec || timeout.tv_usec) {
to = &timeout;
} else {
to = NULL;
}
do {
if (select(nfds, &readfds, NULL, NULL, to) <= 0) {
#if OPTION_ZAP_RESP_LENGTH
len = 0;
#endif
break;
}
len += read(fd, readbuf + len, BUFSIZE - len);
readbuf[len] = '\0';
DBG("%s we have read (%d) %.*s\n", timestamp(), len, 16, readbuf);
if (strstr(readbuf, "\r\nOK\r\n")) {
break;
}
} while (!strstr(readbuf, "\r\nERROR\r\n"));
return len;
}
ssize_t
SendCmd(int fd, const void *cmd, size_t size)
{
return (write(fd, cmd, size) == -1) ? -1 : 0;
}
ssize_t
SendStrCmd(int fd, const char *cmd)
{
return SendCmd(fd, cmd, strlen(cmd));
}
ssize_t
SendAT(int fd)
{
return SendStrCmd(fd, "AT\r");
}
int
AT(int fd)
{
int i;
SendAT(fd);
i = 0;
do {
if (ReadResp(fd, 0, 500000)) {
return 1;
}
i++;
SendAT(fd);
} while (i != 15);
return 0;
}
int
lockcheck(void)
{
int fd;
int len;
fd = InitConn(SPEED);
AT(fd);
forever {
forever {
SendStrCmd(fd, "at+cpin?\r");
len = ReadResp(fd, 0, 100000);
if (len > 0) {
break;
}
AT(fd);
AT(fd);
}
readbuf[len] = 0;
fprintf(LogFile, "%s\n", readbuf);
fflush(LogFile);
if (strstr(readbuf, "PH-NET")) {
close(fd);
return 1;
}
if (strstr(readbuf, "OK")) {
break;
}
sleep(1);
}
close(fd);
return 0;
}
int
pincheck(void)
{
int fd;
int len;
fd = InitConn(SPEED);
AT(fd);
forever {
do {
forever {
SendStrCmd(fd, "at+cpin?\r");
len = ReadResp(fd, 0, 100000);
if (len > 0) {
break;
}
AT(fd);
AT(fd);
}
readbuf[len] = 0;
} while (strstr(readbuf, "SIM PIN"));
if (strstr(readbuf, "OK")) {
break;
}
sleep(1);
}
close(fd);
return 0;
}
int
atping(void)
{
int fd;
fd = InitConn(SPEED);
AT(fd);
return close(fd);
}
char *
BasebandVersion(void)
{
static char ret[16];
int retry;
int fd;
int len;
char *p, *ptr;
retry = 0;
ret[15] = '\0';
ret[0] = '\0';
fd = InitConn(SPEED);
AT(fd);
do {
SendStrCmd(fd, "AT+XGENDATA\r");
len = ReadResp(fd, 0, 100000);
if (len) {
if (len > 0) {
ptr = strstr(readbuf, "ICE3_MODEM_");
if (ptr) {
strncpy(ret, ptr + 11, 15);
for (p = ret; *p; p++) {
if (*p == '_') {
*p = '\0';
break;
}
}
break;
}
} else {
AT(fd);
}
}
} while (++retry != 50);
close(fd);
DBG("%s BasebandVersion got [%s]\n", timestamp(), ret);
return ret;
}
int
atprog(const char *cmds[], int num)
{
int i, j;
int fd;
fd = InitConn(SPEED);
if (!AT(fd)) {
return -1;
}
for (i = 0; i < num; i++) {
DBG("%s atprog -> %.*s\n", timestamp(), 16, cmds[i]);
int txlen;
char *buf = malloc(strlen(cmds[i]) + 7);
strcpy(buf, cmds[i]);
txlen = strlen(buf);
if (buf[txlen - 1] == '\n') {
buf[txlen - 1] = '\0';
}
strcat(buf, "\r");
txlen = strlen(buf);
if (txlen) {
j = 0;
forever {
DBG("%s atprog... send\n", timestamp());
SendStrCmd(fd, buf);
if (ReadResp(fd, 0, 100000) > 0)
break;
DBG("%s atprog... RETRY\n", timestamp());
AT(fd);
++j;
AT(fd);
if (j == 51)
{
DBG("%s atprog... TIMEOUT?\n", timestamp());
goto done;
}
}
free(buf);
}
}
done:
close(fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment