line source
/*
* This program is a contender for the title of the ugliest hack
* in the FreeCalypso project. It will attempt to break into a
* locked-down TracFone C139 by mimicking the actions of the
* mot931c.exe TF "unlocker".
*/
#include <sys/types.h>
#include <sys/errno.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include "../include/pktmux.h"
#include "../include/limits.h"
extern int target_fd;
extern char *baudrate_name;
extern u_char rxpkt[];
extern size_t rxpkt_len;
char *logfname;
FILE *logF;
time_t logtime;
int no_output; /* for output.c */
int wakeup_after_sec = 7;
/* see ../../target-utils/tf-breakin/payload.S for the source */
static u_char iram_payload[112] = {
0xD3, 0xF0, 0x21, 0xE3, 0x58, 0x10, 0x9F, 0xE5,
0xF5, 0x00, 0xA0, 0xE3, 0xB2, 0x00, 0xC1, 0xE1,
0xA0, 0x00, 0xA0, 0xE3, 0xB2, 0x00, 0xC1, 0xE1,
0x48, 0x60, 0x9F, 0xE5, 0x05, 0x00, 0xD6, 0xE5,
0x20, 0x00, 0x10, 0xE3, 0xFC, 0xFF, 0xFF, 0x0A,
0x2C, 0x10, 0x8F, 0xE2, 0x06, 0x20, 0xA0, 0xE3,
0x01, 0x00, 0xD1, 0xE4, 0x00, 0x00, 0xC6, 0xE5,
0x01, 0x20, 0x52, 0xE2, 0xFB, 0xFF, 0xFF, 0x1A,
0x05, 0x00, 0xD6, 0xE5, 0x40, 0x00, 0x10, 0xE3,
0xFC, 0xFF, 0xFF, 0x0A, 0x18, 0x10, 0x9F, 0xE5,
0x01, 0x2C, 0xA0, 0xE3, 0xB0, 0x20, 0xC1, 0xE1,
0x00, 0xF0, 0xA0, 0xE3, 0x02, 0x02, 0x02, 0x4F,
0x4B, 0x02, 0x00, 0x00, 0x02, 0xF8, 0xFF, 0xFF,
0x00, 0x58, 0xFF, 0xFF, 0x10, 0xFB, 0xFF, 0xFF
};
static unsigned iram_load_addr = 0x800000;
static unsigned stack_smash_addr = 0x837C54;
static u_char stack_smash_payload[4];
static char *target_tty_port;
static void
send_compal_memwrite(addr, payload, payload_len)
unsigned addr;
u_char *payload;
{
u_char pkt[MAX_PKT_TO_TARGET];
int i, csum, csum_offset;
pkt[0] = RVT_TM_HEADER;
pkt[1] = 0x40; /* Compal's non-standard addition */
pkt[2] = addr;
pkt[3] = addr >> 8;
pkt[4] = addr >> 16;
pkt[5] = addr >> 24;
bcopy(payload, pkt + 6, payload_len);
csum_offset = payload_len + 6;
csum = 0;
for (i = 1; i < csum_offset; i++)
csum ^= pkt[i];
pkt[i] = csum;
send_pkt_to_target(pkt, i + 1);
}
main(argc, argv)
char **argv;
{
extern char *optarg;
extern int optind;
int c;
fd_set fds;
baudrate_name = "57600"; /* what C139 firmware uses */
while ((c = getopt(argc, argv, "a:B:l:s:w:")) != EOF)
switch (c) {
case 'a':
iram_load_addr = strtoul(optarg, 0, 16);
continue;
case 'B':
baudrate_name = optarg;
continue;
case 'l':
logfname = optarg;
continue;
case 's':
stack_smash_addr = strtoul(optarg, 0, 16);
continue;
case 'w':
wakeup_after_sec = strtoul(optarg, 0, 0);
continue;
case '?':
default:
usage: fprintf(stderr,
"usage: %s [options] ttyport\n", argv[0]);
exit(1);
}
if (argc - optind != 1)
goto usage;
open_target_serial(argv[optind]);
target_tty_port = argv[optind];
set_serial_nonblock(0);
setlinebuf(stdout);
if (logfname) {
logF = fopen(logfname, "w");
if (!logF) {
perror(logfname);
exit(1);
}
setlinebuf(logF);
fprintf(logF, "*** Log of TFC139 break-in session ***\n");
}
time(&logtime);
output_line("Sending IRAM payload");
send_compal_memwrite(iram_load_addr, iram_payload, sizeof iram_payload);
stack_smash_payload[0] = iram_load_addr;
stack_smash_payload[1] = iram_load_addr >> 8;
stack_smash_payload[2] = iram_load_addr >> 16;
stack_smash_payload[3] = iram_load_addr >> 24;
for (;;) {
FD_ZERO(&fds);
FD_SET(target_fd, &fds);
c = select(target_fd+1, &fds, 0, 0, 0);
time(&logtime);
if (c < 0) {
if (errno == EINTR)
continue;
perror("select");
exit(1);
}
if (FD_ISSET(target_fd, &fds))
process_serial_rx();
}
}
static void
handle_etm_response()
{
char msgbuf[80];
if (rxpkt_len != 4 || rxpkt[1] != 0x40 || rxpkt[2] || rxpkt[3] != 0x40){
output_line("ETM response differs from expected");
return;
}
sprintf(msgbuf, "Sending stack smash write at 0x%x", stack_smash_addr);
output_line(msgbuf);
send_compal_memwrite(stack_smash_addr, stack_smash_payload, 4);
stack_smash_addr += 4;
}
handle_rx_packet()
{
if (rxpkt_len == 2 && rxpkt[0] == 'O' && rxpkt[1] == 'K') {
output_line(
"Success: target should now be in boot ROM download wait");
printf("You can now run fc-loadtool -h compal -c none %s\n",
target_tty_port);
exit(0);
}
switch (rxpkt[0]) {
case RVT_RV_HEADER:
if (rxpkt_len < 6)
goto unknown;
print_rv_trace();
return;
case RVT_L1_HEADER:
print_l1_trace();
return;
case RVT_L23_HEADER:
print_g23_trace();
return;
case RVT_TM_HEADER:
print_etm_output_raw();
handle_etm_response();
return;
default:
unknown:
print_unknown_packet();
}
}