Decompiled msinst.exe
msinst.exe 用来将IPL安装到memorystick上的程序。他的工作流程:
1. 检查用户所指定的盘符是否对应一个移动设备(避免不小心干掉系统盘之类)
2. 检查从memory stick第16个扇区开始到绝对扇区之间是否有足够的空间来容纳IPL
3. 如果上面的检查通过,将IPL从第16个扇区开始写入
下面是逆向出来的代码,加入了将指定的扇区之间的数据复制到文件的功能。
/*
===============================================================
The original msinst.exe console output:
---------------------------------------------------------------
PSP MS IPL Installer
Load IPL code pspboot.bin
15630 bytes(4 block) readed
Target DRIVE is 1
Check partation Sector
boot status 0x80
start head 0x00
start sec/cyl 0x0401
partation type 0x0B
last head 0xFE
last sec/cyl 0x823F
abs sector 0x0000FB04
ttl sector 0x001F21BF
signature 0xAA55
Check BPB Sector
signature AA55
Check free reserved sector:OK
Write ABS Sector 0x10 to 0x2F
Are You Sure ?[Y]n
===============================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define SECTOR_SIZE 512
typedef unsigned short u16;
typedef unsigned char u8;
typedef unsigned int u32;
char RootPathName[256];
char FileName[256];
u8 data[0x100000];
/*
===============================================================
GetDriveType
for c: will reture 3
#define DRIVE_REMOVABLE 2
#define DRIVE_FIXED 3
===============================================================
DeviceIoControl
command 0x560000 get data
g:
0x0012FE38 01 00 00 00 00 00 00 00 01 00 00 00 b0 35 21 86 .............5!.
0x0012FE48 00 08 f6 01 00 00 00 00 00 7e 43 3e 00 00 00 00 .........~C>....
c:
0x0012FE38 01 00 00 00 a8 80 27 86 00 00 00 00 a0 80 27 86 .....€'......€'.
0x0012FE48 00 7e 00 00 00 00 00 00 00 02 02 88 13 00 00 00 .~..............
d:
0x0012FE38 01 00 00 00 f4 c3 41 94 00 00 00 00 01 00 04 00 ......A.........
0x0012FE48 00 fe 02 88 13 00 00 00 00 a2 02 6a 18 00 00 00 ...........j....
e:
0x0012FE38 01 00 00 00 e0 97 e3 85 00 00 00 00 56 00 43 00 ............V.C.
0x0012FE48 00 1e 06 f2 2b 00 00 00 00 02 a0 93 1e 00 00 00 ....+...........
===============================================================
*/
int read_sector(u32 devid, int offset, int cnt, LPVOID lpBuffer)
{
int result;
HANDLE hFile;
DWORD dwRet;
sprintf(FileName, "%s%d", "\\\\.\\PHYSICALDRIVE", devid);
if (devid){
hFile = CreateFile(FileName, 0x80000000u, 1u, 0, 3u, 0, 0);
if ( hFile == (HANDLE)-1 ){
printf("[erro] Cannot open device %s\n", FileName);
result = -1;
}else{
if (SetFilePointer(hFile, offset*SECTOR_SIZE, 0, 0) == (offset*SECTOR_SIZE)){
if ( ReadFile(hFile, lpBuffer, cnt*SECTOR_SIZE, &dwRet, 0) == 1 ){
CloseHandle(hFile);
result = 0;
}else{
printf("[erro] Error in ReadFile.\n");
CloseHandle(hFile);
result = -1;
}
}else{
printf("[erro] Error setting filepointer.\n");
CloseHandle(hFile);
result = -1;
}
}
}else{
printf("[erro] Drive 0 failsafe.\n");
result = -1;
}
return result;
}
int write_sector(u32 devid, int offset, int cnt, LPCVOID lpBuffer)
{
int result;
HANDLE hFile;
DWORD dwRet;
sprintf(FileName, "%s%d", "\\\\.\\PHYSICALDRIVE", devid);
if (devid){
hFile = CreateFile(FileName, 0xC0000000u, 1u, 0, 3u, 0, 0);
if ( hFile == (HANDLE)-1 ){
printf("[erro] Cannot open device %s\n", FileName);
return -1;
}else{
if (SetFilePointer(hFile, offset*SECTOR_SIZE, 0, 0) == (offset*SECTOR_SIZE)){
if ( WriteFile(hFile, lpBuffer, cnt*SECTOR_SIZE, &dwRet, 0) == 1 ){
CloseHandle(hFile);
result = 0;
}else{
printf("[erro] Error in WriteFile.\n");
CloseHandle(hFile);
result = -1;
}
}else{
printf("[erro] Error setting filepointer.\n");
CloseHandle(hFile);
result = -1;
}
}
}else{
printf("[erro] Drive 0 failsfe.\n");
result = -1;
}
return result;
}
int dump_sector(int devid, int start, int end)
{
u8 *buf;
FILE *fp;
int buf_size;
fp = fopen("dump.bin", "wb");
if(NULL == fp){
printf("[erro] Error to open file [%s]\n", "dump.bin");
return -1;
}
buf_size = (end-start+1)*SECTOR_SIZE;
buf = (u8 *)malloc(buf_size);
read_sector(devid, start, end-start+1, (void*)buf);
fwrite(buf, buf_size, 1, fp);
free(buf);
fclose(fp);
}
int load_payload(char *fname)
{
FILE* fp;
int file_size;
fp = fopen(fname, "rb");
if(NULL == fp){
printf("[erro] open datafile [%s] failed\n", fname);
return -1;
}
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
fseek(fp, 0, 0);
fread(data, file_size, 1, fp);
fclose(fp);
return file_size;
}
int check_removable(char lable)
{
int dev_type = 0;
DWORD dwOutput;
HANDLE file;
HRESULT ret;
unsigned char OutBuffer[0x20];
sprintf(RootPathName, "%c:\\", lable);
dev_type = GetDriveType(RootPathName);
if(DRIVE_REMOVABLE != dev_type){
printf("[erro] Drive %c is invalid or not removable\n", lable);
return -1;
}
sprintf(RootPathName, "\\\\.\\%c:", lable);
file = CreateFile(RootPathName, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
if ( file == (HANDLE)-1 ){
printf("[erro] Cannot open logical drive.\n");
return -1;
}
ret = DeviceIoControl(file, 0x560000, 0, 0, OutBuffer, 0x20, &dwOutput, 0);
if ( GetLastError() == 234 || *(u32 *)OutBuffer != 1 ){
printf("[erro] Logical drive has more than a physical drive. Cannot handle it.\n");
CloseHandle(file);
return -1;
}
if(0 == ret){
printf("[erro] Error 0x%08X in DeviceIoControl.\n", 0);
CloseHandle(file);
return -1;
}
CloseHandle(file);
return *(u32*)(OutBuffer+8);
}
int main(int argc, char* argv[])
{
int devid, ldrscnt=4, abs_sec=0, ldrsize;
u8 buf[SECTOR_SIZE];
ldrsize = load_payload("ipl_ms.bin");
if(ldrsize<0) return -1;
//calc block cnt for 4KB
ldrscnt = (signed int)(ldrsize + 4095) / 4096;
devid = check_removable('g');
if(devid<0) return -1;
printf("\nTarget DRIVE is %d\n", devid);
printf("Check partation Sector\n");
if(read_sector(devid, 0, 1, (void*)buf) < 0){
printf("[erro] Can't read partation sector\n");
return -1;
}
abs_sec = *(u16 *)(buf+0x1c6);
printf("boot status 0x%02X\n", *(u8 *)(buf+0x1be));
printf("start head 0x%02X\n", *(u8 *)(buf+0x1bf));
printf("start sec/cyl 0x%04X\n", *(u16 *)(buf+0x1c0));
printf("partation type 0x%02X\n", *(u8 *)(buf+0x1c2));
printf("last head 0x%02X\n", *(u8 *)(buf+0x1c3));
printf("last sec/cyl 0x%04X\n", *(u16 *)(buf+0x1c4));
printf("abs sector 0x%08X\n", abs_sec);
printf("ttl sector 0x%08X\n", *(u32 *)(buf+0x1ca));
printf("signature 0x%04X\n", *(u16 *)(buf+0x1fe));
if( *(u16 *)(buf+0x1fe) != 0xAA55 ){
printf("[erro] Bad Signature\n");
return -1;
}
printf("Check BPB Sector\n");
if ( read_sector(devid, *(u16 *)(buf+0x1c6), 1, (void*)buf) >= 0 ){
printf("signature 0x%04X\n", *(u16 *)(buf+0x1fe));
if( *(u16 *)(buf+0x1fe) != 0xAA55 ){
printf("[erro] Bad Signature\n");
return -1;
}
printf("Check free reserved sector:");
if((abs_sec - 16)/8<ldrscnt){
printf("[erro] to small reserved sectors\n");
return -1;
}
printf("OK\n");
//printf("Write ABS Sector 0x%X to 0x%X\n", 16, 8*ldrscnt+15);
//write_sector(devid, 16, 8*ldrscnt, data);
printf("Dump ABS Sector 0x%X to 0x%X\n", 0x40, 0x47);
dump_sector(devid, 0x40, 0x47);
}
return 0;
}