[HTC Wildfire S] no.human.being:
I've got a JTAG interface for ARM, but I haven't got a suitable adapter yet. The phone doesn't use the standard JTAG pin header, as this would be far too large to fit inside the phone case so you need an adapter to access the miniaturized connectors. I also cannot operate the tools (OpenOCD), but I know some of my fellow students can.

I've got a better idea than cracking the recovery. The exploit already creates a 1-to-1 copy of the contents of mtd3 (which is the partition where "/system" is on) on the SD card. I'm mounting this image to "/system" via a loop device. Access to external storage is much slower than the on-chip NAND, so it might seriously degrade system performance, but at least we should be able to continue working.

I'm trying out that new version of the exploit and will publish it when it works. Stay tuned!

EDIT:

# mount -t yaffs2 -o loop /mnt/sdcard/dump.img /system
mount: mounting /dev/block/loop0 on /system failed: Invalid argument
#

Mmmh. Anyone knows why this is failing? It's the way that drive images are mounted on a standard Linux system.

EDIT 2:

This is the new exploit code. Unfortunately, step 3 is not possible.

/*
* S-OFF Exploit for HTC Wildfire S
* To be executed after obtaining temproot via zergRush
*/

#include <stdio.h>
#include <stdlib.h>
const int BLOCKSIZE = 4096;
const char* gcDevice = "/dev/mtd/mtd3";
const char* gcPath = "/system";
const char* gcDump = "/mnt/sdcard/dump.img";
const char* gcPatch = "/mnt/sdcard/patch.img";
FILE* fdRead;
FILE* fdWrite;
char* buf;

void patch(char* buf, unsigned long length, unsigned long offset)
{
int i;

for (i = 0; i < length; i++)
{
unsigned long addr = offset + i;

// Super CID
if ((addr >= 0x00000200) && (addr <= 0x00000207))
buf[i] = 0x31;

// S-OFF
if (addr == 0x00000a00)
buf[i] ^= 0x01;

// SIM lock
if (addr == 0x00080000)
buf[i] = 0x78;
if (addr == 0x00080001)
buf[i] = 0x56;
if (addr == 0x00080002)
buf[i] = 0xf3;
if (addr == 0x00080003)
buf[i] = 0xc9;
if ((addr >= 0x00080004) && (addr <= 0x000807fb))
buf[i] = 0x00;
if (addr == 0x000807fc)
buf[i] = 0x49;
if (addr == 0x000807fd)
buf[i] = 0x53;
if (addr == 0x000807fe)
buf[i] = 0xf4;
if (addr == 0x000807ff)
buf[i] = 0x7d;
}

}

void waitthis(int sec)
{
int i;

for (i = sec; i >= 0; i--)
{
printf("%d ", i);
sleep(1);
}

printf("\n");
}

int step_one()
{
printf("1. Dump the NAND contents to SD-Card\n");
int size = 0;
unsigned long offset = 0;
waitthis(5);
printf("Opening %s\n", gcDevice);
fdRead = fopen(gcDevice, "rb");

if (fdRead == NULL)
{
printf("Opening %s failed!\n", gcDevice);
return(-1);
}

printf("%s open\n", gcDevice);
printf("Opening %s\n", gcDump);
fdWrite = fopen(gcDump, "wb");

if (fdWrite == NULL)
{
printf("Opening %s failed!\n", gcDump);
return(-1);
}

printf("%s open\n", gcDump);
size = fread(buf, 1, BLOCKSIZE, fdRead);

do
{
printf("Step 1, Offset: %x\n", offset);
fwrite(buf, size, 1, fdWrite);
offset += size;
size = fread(buf, 1, BLOCKSIZE, fdRead);
}
while (!feof(fdRead));

fwrite(buf, size, 1, fdWrite);
fflush(fdWrite);
printf("At address: %x\n", offset);
fclose(fdWrite);
fclose(fdRead);
return(0);
}

int step_two()
{
int size;
unsigned long offset;
int i;
printf("2. Patch the dump with S-OFF, SUID set and SimLock unlocked\n");
waitthis(5);
printf("Opening %s\n", gcDump);
fdRead = fopen(gcDump, "rb");

if (fdRead == NULL)
{
printf("Opening %s failed!\n", gcDump);
return(-1);
}

printf("%s open\n", gcDump);
printf("Opening %s\n", gcPatch);
fdWrite = fopen(gcPatch, "wb");

if (fdWrite == NULL)
{
printf("Opening %s failed!\n", gcPatch);
return(-1);
}

printf("%s open\n", gcPatch);
size = fread(buf, 1, BLOCKSIZE, fdRead);
offset = 0;

do
{
printf("Step 2, Offset: %x\n", offset);
patch(buf, size, offset);
fwrite(buf, size, 1, fdWrite);
size = fread(buf, 1, BLOCKSIZE, fdRead);
offset += size;
}
while (!feof(fdRead));

patch(buf, size, offset);
fwrite(buf, size, 1, fdWrite);
fflush(fdWrite);
printf("At address: %x\n", offset);
fclose(fdWrite);
fclose(fdRead);
return(0);
}

int step_three()
{
printf("3. Mount the image as '/system'\n");
waitthis(5);
sprintf(buf, "mount -o loop %s %s", gcDump, gcPath);
system(buf);
return(0);
}

int step_four()
{
printf("4. Erase the NAND memory\n");
waitthis(5);
sprintf(buf, "flash_eraseall %s", gcDevice);
system(buf);
return(0);
}

int step_five()
{
int size;
unsigned long offset;
printf("5. Write the patched dump back to NAND\n");
waitthis(5);
printf("Opening %s\n", gcPatch);
fdRead = fopen(gcPatch, "rb");

if (fdRead == NULL)
{
printf("Opening %s failed!\n", gcPatch);
return(-1);
}

printf("%s open\n", gcPatch);
printf("Opening %s\n", gcDevice);
fdWrite = fopen(gcDevice, "wb");

if (fdWrite == NULL)
{
printf("Opening %s failed!\n", gcDevice);
return(-1);
}

printf("%s open\n", gcDevice);
offset = 0;
size = fread(buf, 1, BLOCKSIZE, fdRead);

do
{

if ((offset % 4096) == 0)
printf("Step 1, Offset: %x\n", offset);

fwrite(buf, size, 1, fdWrite);
size = fread(buf, 1, BLOCKSIZE, fdRead);
offset += size;
}
while (!feof(fdRead));

fwrite(buf, size, 1, fdWrite);
fflush(fdWrite);
printf("At address: %x\n", offset);
fclose(fdWrite);
fclose(fdRead);
return(0);
}

int main()
{
int size;
unsigned long offset;
int i;
int result = 0;
printf("Allocating memory for buffer ...\n");
buf = (char*)malloc(BLOCKSIZE * sizeof(char));

for (i = 1; i <= 5; i++)
{

switch(i)
{
case 1:
result = step_one();
break;
case 2:
result = step_two();
break;
case 3:
result = step_three();
break;
case 4:
// result = step_four();
break;
case 5:
// result = step_five();
break;
default:
result = -1;
break;
}

if (result != 0)
break;
}

printf("Freeing memory allocated for buffer ...\n");
free(buf);
printf("Done! Please shut down your phone and remove the battery to clean up the mess that this exploit might have left.\n");
return(0);
}