added injection feature

code still needs a lot of clean up.
injection needs testing.
todo:
update readme
This commit is contained in:
Maschell 2015-10-23 22:33:18 +02:00
parent 3939be8263
commit 6cdc9276aa
12 changed files with 791 additions and 95 deletions

11
.gitignore vendored
View File

@ -41,3 +41,14 @@ $RECYCLE.BIN/
Network Trash Folder
Temporary Items
.apdisk
saviine/installer/bin/*
saviine/client/build/*
saviine/server/src/bin/logs/*
saviine/server/src/bin/saviine_root/*
saviine/server/src/bin/saviine_server.pdb
saviine/server/src/bin/saviine_server.vshost.exe.manifest
saviine/server/src/obj/x86/Debug/saviine_server.exe
saviine/server/src/obj/x86/Debug/saviine_server.pdb
saviine/server/src/bin/saviine_server.vshost.exe
saviine/server/src/bin/saviine_server.exe.config
saviine/server/src/bin/saviine_server.vshost.exe.config

View File

@ -4,10 +4,7 @@
extern res name(__VA_ARGS__); \
res (* real_ ## name)(__VA_ARGS__) __attribute__((section(".magicptr"))); \
res my_ ## name(__VA_ARGS__)
#define BYTE_LOG_STR 0xfb
#define DEBUG_LOG 0
extern FSStatus FSOpenDir(FSClient *pClient, FSCmdBlock *pCmd, const char *path, int *dh, FSRetFlag errHandling);
extern FSStatus FSReadDir(FSClient *pClient, FSCmdBlock *pCmd, int dh, FSDirEntry *dir_entry, FSRetFlag errHandling);
extern FSStatus FSChangeDir(FSClient *pClient, FSCmdBlock *pCmd, const char *path, FSRetFlag errHandling);
@ -15,17 +12,13 @@ extern FSStatus FSCloseDir(FSClient *pClient, FSCmdBlock *pCmd, int dh, FSRetFla
extern FSStatus FSReadFile(FSClient *pClient, FSCmdBlock *pCmd, void *buffer, int size, int count, int fd, int flag, int error);
extern FSStatus FSSetPosFile(FSClient *pClient, FSCmdBlock *pCmd, int fd, int pos, int error);
extern FSStatus FSCloseFile (FSClient *pClient, FSCmdBlock *pCmd, int fd, int error);
extern FSStatus FSMakeDir(FSClient *pClient, FSCmdBlock *pCmd,const char *path, FSRetFlag errHandling);
extern FSStatus FSRemove(FSClient *pClient, FSCmdBlock *pCmd, const char *path, FSRetFlag errHandling);
extern void OSDynLoad_Acquire (char* rpl, unsigned int *handle);
extern void OSDynLoad_FindExport (unsigned int handle, int isdata, char *symbol, void *address);
void GX2WaitForVsync(void);
static void dump_saves(void *pClient, void *pCmd,int error, int client);
static int strlen(char* path) {
int i = 0;
while (path[i++])
;
return i;
}
static void handle_saves(void *pClient, void *pCmd,int error, int client);
static void hook(void * pClient,void * pCmd, int error, int client);
DECL(int, FSAInit, void) {
if ((int)bss_ptr == 0x0a000000) {
@ -56,6 +49,31 @@ DECL(int, FSADelClient, int client) {
return real_FSADelClient(client);
}
static int strlen(char* path) {
int i = 0;
while (path[i++])
;
return i;
}
static int strcmp(const char *s1, const char *s2)
{
while(*s1 && *s2)
{
if(*s1 != *s2) {
return -1;
}
s1++;
s2++;
}
if(*s1 != *s2) {
return -1;
}
return 0;
}
static int client_num_alloc(void *pClient) {
int i;
@ -100,8 +118,17 @@ DECL(int, FSDelClient, void *pClient) {
}
return real_FSDelClient(pClient);
}
DECL(int, FSWriteFile,FSClient *pClient, FSCmdBlock *pCmd, const void *source,int size, int count, int fileHandle, int flag,FSRetFlag error) {
return real_FSWriteFile(pClient,pCmd,source,size,count,fileHandle,flag,error);
}
DECL(int, FSFlushQuota,FSClient *pClient,FSCmdBlock *pCmd,const char *path,FSRetFlag error) {
return real_FSFlushQuota(pClient,pCmd,path,error);
}
DECL(int, FSAddClientEx, void *r3, void *r4, void *r5) {
int res = real_FSAddClientEx(r3, r4, r5);
if(bss.saveFolderChecked == 1) return res;
if ((int)bss_ptr != 0x0a000000 && res >= 0) {
//int client = client_num_alloc(r3);
@ -118,35 +145,77 @@ DECL(int, FSAddClientEx, void *r3, void *r4, void *r5) {
FSAddClient(pClient, FS_RET_NO_ERROR);
int client = client_num_alloc(pClient);
if(client < MAX_CLIENT && client >= 0) {
cafiine_connect(&bss.socket_fs[client]);
cafiine_connect(&bss.socket_fs[client]);
bss.logsock = bss.socket_fs[client];
}else{
goto error;
}
// Init command block.
FSInitCmdBlock(pCmd);
dump_saves(pClient, pCmd,-1, client);
hook(pClient, pCmd,-1, client);
bss.saveFolderChecked = 2;
error:
real_FSDelClient(pClient);
error: real_FSDelClient(pClient);
free(pClient);
free(pCmd);
}
}
//cafiine_connect(&bss.socket_fs[client]);
//}
//}
}
return res;
}
static int remove_files_in_dir(void * pClient,void * pCmd, char * path, int handle){
int ret = 0;
if ((ret = FSOpenDir(pClient, pCmd, path, &handle, FS_RET_ALL_ERROR)) == FS_STATUS_OK){
char buffer[strlen(path) + 25];
__os_snprintf(buffer, sizeof(buffer), "remove files in dir %s",path);
log_string(bss.logsock, buffer, BYTE_LOG_STR);
FSDirEntry dir_entry;
while (FSReadDir(pClient, pCmd, handle, &dir_entry, FS_RET_ALL_ERROR) == FS_STATUS_OK)
{
char full_path[255];
int i=0;
char *path_ptr = (char *)path;
while(*path_ptr) {
full_path[i++] = *path_ptr++;
}
full_path[i++] = '/';
char *dir_name_ptr = (char *)dir_entry.name;
while(*dir_name_ptr) {
full_path[i++] = *dir_name_ptr++;
}
full_path[i++] = '\0';
char buffer[strlen(full_path) + 50];
__os_snprintf(buffer, sizeof(buffer), "deleting %s",full_path);
log_string(bss.logsock, buffer, BYTE_LOG_STR);
if((ret = FSRemove(pClient,pCmd,full_path,-1)) < 0){
__os_snprintf(buffer, sizeof(buffer), "error: %d on %s",ret,full_path);
log_string(bss.logsock, buffer, BYTE_LOG_STR);
return -1;
}
}
if((FSCloseDir(pClient, pCmd, handle, FS_RET_NO_ERROR)) <=0 ){
log_string(bss.logsock, "error while closing dir", BYTE_LOG_STR);
}
}
return 0;
}
static void hook(void * pClient,void * pCmd, int error, int client){
log_string(bss.logsock, "hook", BYTE_LOG_STR);
handle_saves(pClient, pCmd,-1, client);
}
static void init_Save(){
int (*SAVEInit)();
unsigned int save_handle;
OSDynLoad_Acquire("nn_save.rpl", &save_handle);
OSDynLoad_FindExport(save_handle, 0, "SAVEInit", &SAVEInit);
OSDynLoad_FindExport(save_handle, 0, "SAVEInit", (void **)&SAVEInit);
SAVEInit();
}
@ -157,10 +226,10 @@ static long getPesistentID(){
void (*nn_Initialize)(void);
void (*nn_Finalize)(void);
OSDynLoad_Acquire("nn_act.rpl", &nn_act_handle);
OSDynLoad_FindExport(nn_act_handle, 0, "GetPersistentIdEx__Q2_2nn3actFUc", &GetPersistentIdEx);
OSDynLoad_FindExport(nn_act_handle, 0, "GetSlotNo__Q2_2nn3actFv", &GetSlotNo);
OSDynLoad_FindExport(nn_act_handle, 0, "Initialize__Q2_2nn3actFv", &nn_Initialize);
OSDynLoad_FindExport(nn_act_handle, 0, "Finalize__Q2_2nn3actFv", &nn_Finalize);
OSDynLoad_FindExport(nn_act_handle, 0, "GetPersistentIdEx__Q2_2nn3actFUc", (void **)&GetPersistentIdEx);
OSDynLoad_FindExport(nn_act_handle, 0, "GetSlotNo__Q2_2nn3actFv", (void **)&GetSlotNo);
OSDynLoad_FindExport(nn_act_handle, 0, "Initialize__Q2_2nn3actFv", (void **)&nn_Initialize);
OSDynLoad_FindExport(nn_act_handle, 0, "Finalize__Q2_2nn3actFv", (void **)&nn_Finalize);
nn_Initialize(); // To be sure that it is really Initialized
@ -183,7 +252,7 @@ static int dump_dir(void *pClient,int client, void *pCmd, char *path, int error,
char buffer[strlen(path) + 25];
__os_snprintf(buffer, sizeof(buffer), "open dir %s",path);
log_string(bss.socket_fsa[client], buffer, BYTE_LOG_STR);
log_string(bss.logsock, buffer, BYTE_LOG_STR);
FSDirEntry dir_entry;
while (FSReadDir(pClient, pCmd, dir_handle, &dir_entry, FS_RET_ALL_ERROR) == FS_STATUS_OK)
{
@ -203,14 +272,14 @@ static int dump_dir(void *pClient,int client, void *pCmd, char *path, int error,
if((dir_entry.stat.flag&FS_STAT_FLAG_IS_DIRECTORY) == FS_STAT_FLAG_IS_DIRECTORY){
log_string(bss.socket_fsa[client], "-> dir", BYTE_LOG_STR);
log_string(bss.logsock, "-> dir", BYTE_LOG_STR);
dump_dir(pClient,client, pCmd,full_path,-1,my_handle);
}else{
//DUMP
ret = FSOpenFile(pClient, pCmd, full_path, "r", &my_handle, FS_RET_ALL_ERROR);
if (ret >= 0) {
__os_snprintf(buffer, sizeof(buffer), "dumping %s",dir_entry.name);
log_string(bss.socket_fsa[client], buffer, BYTE_LOG_STR);
log_string(bss.logsock, buffer, BYTE_LOG_STR);
int my_ret = cafiine_send_handle(bss.socket_fsa[client], client, full_path, my_handle);
@ -220,7 +289,7 @@ static int dump_dir(void *pClient,int client, void *pCmd, char *path, int error,
int ret2;
while ((ret2 = FSReadFile(pClient, pCmd, buffer, 1, size, my_handle, 0, 0)) > 0)
cafiine_send_file(bss.socket_fsa[client], buffer, ret2, my_handle);
cafiine_fclose(bss.socket_fsa[client], &ret2, my_handle);
cafiine_fclose(bss.socket_fsa[client], &ret2, my_handle,1);
FSSetPosFile(pClient, pCmd, my_handle, 0, FS_RET_ALL_ERROR);
free(buffer);
FSCloseFile(pClient, pCmd, my_handle, -1);
@ -228,7 +297,7 @@ static int dump_dir(void *pClient,int client, void *pCmd, char *path, int error,
char type[2];
type[0] = '9' + ret;
type[1] = '\0';
log_string(bss.socket_fsa[client], type, BYTE_LOG_STR);
log_string(bss.logsock, type, BYTE_LOG_STR);
}
}
@ -238,22 +307,145 @@ static int dump_dir(void *pClient,int client, void *pCmd, char *path, int error,
return 0;
}
static void dump_saves(void *pClient, void *pCmd,int error, int client){
static void handle_saves(void *pClient, void *pCmd,int error, int client){
log_string(bss.logsock, "handle_saves", BYTE_LOG_STR);
init_Save();
long id = getPesistentID();
log_string(bss.socket_fsa[client], "dumping user savedata", BYTE_LOG_STR);
log_string(bss.logsock, "user savedata", BYTE_LOG_STR);
if(id >= 0x80000000 && id <= 0x90000000){
char savepath[20];
__os_snprintf(savepath, sizeof(savepath), "/vol/save/%08x",id);
dump_dir(pClient,client,pCmd,savepath,-1,50);
int mode;
__os_snprintf(savepath, sizeof(savepath), "/vol/save/%08x",id);
log_string(bss.logsock, "Getting mode!", BYTE_LOG_STR);
if(getMode(bss.socket_fsa[client],&mode)){
if(mode == BYTE_MODE_D){
log_string(bss.logsock, "dump mode!", BYTE_LOG_STR);
dump_dir(pClient,client,pCmd,savepath,-1,50);
}else if(mode == BYTE_MODE_I){
log_string(bss.logsock, "inject mode", BYTE_LOG_STR);
log_string(bss.logsock, "deleting current save", BYTE_LOG_STR);
remove_files_in_dir(pClient,pCmd,savepath,0);
injectFiles(pClient,pCmd,savepath,"/",-1);
log_string(bss.logsock, "flushing quota", BYTE_LOG_STR);
FSFlushQuota(pClient,pCmd,savepath,-1);
}
}
}
/*
log_string(bss.logsock, "dumping common savedata", BYTE_LOG_STR);
dump_dir(pClient,client,pCmd,"/vol/save/common/",error,60);
log_string(bss.logsock, "done!", BYTE_LOG_STR);*/
}
#define BUFFER_SIZE (1024)*100
void injectFiles(void *pClient, void *pCmd, char * path,char * relativepath, int error){
//FSStatus (*FSWriteFileWithPos) (FSClient *pClient, FSCmdBlock *pCmd, const void *source,int size,int count,int fpos,int fileHandle,int flag,FSRetFlag errHandling);
int client = client_num(pClient);
int type = 0;
log_string(bss.logsock, "injecting files", BYTE_LOG_STR);
char namebuffer[255];
char logbugger[255];
int filesize = 0;
int buf_size = BUFFER_SIZE;
char * pBuffer;
do{
buf_size -= 0x200;
if(buf_size < 0){
log_string(bss.logsock, "error on buffer allocation", BYTE_LOG_STR);
return;
}
pBuffer = (char *)MEMAllocFromDefaultHeapEx(buf_size, 0x40);
}while(!pBuffer);
__os_snprintf(logbugger, sizeof(logbugger), "buffer size: %d bytes",buf_size);
log_string(bss.logsock, logbugger, BYTE_LOG_STR);
while(getFiles(bss.socket_fsa[client],path,namebuffer, &type,&filesize)){
if(DEBUG_LOG)log_string(bss.logsock, "got a file", BYTE_LOG_STR);
char newpath[strlen(path) + 1 + strlen(namebuffer)];
__os_snprintf(newpath, sizeof(newpath), "%s/%s",path,namebuffer);
if(type == BYTE_FILE){
__os_snprintf(logbugger, sizeof(logbugger), "file: %s%s size: %d",relativepath,namebuffer,filesize);
log_string(bss.logsock, logbugger, BYTE_LOG_STR);
if(DEBUG_LOG) log_string(bss.logsock, "downloading it", BYTE_LOG_STR);
int handle = 10;
if(FSOpenFile(pClient, pCmd, newpath,"w+",&handle,-1) >= 0){
if(DEBUG_LOG) log_string(bss.logsock, "file opened and created", BYTE_LOG_STR);
if(filesize > 0){
int myhandle;
int ret = 0;
if((cafiine_fopen(bss.socket_fsa[client], &ret, newpath, "r", &myhandle)) == 0 && ret == 0){
if(DEBUG_LOG)__os_snprintf(logbugger, sizeof(logbugger), "cafiine_fopen with handle %d",myhandle);
if(DEBUG_LOG) log_string(bss.logsock, logbugger, BYTE_LOG_STR);
int size = sizeof(char);
int count = buf_size;
int retsize = 0;
int pos = 0;
while(pos < filesize){
if(DEBUG_LOG) log_string(bss.logsock, "reading", BYTE_LOG_STR);
if(DEBUG_LOG)__os_snprintf(logbugger, sizeof(logbugger), "count %d",count);
if(DEBUG_LOG) log_string(bss.logsock, logbugger, BYTE_LOG_STR);
if(cafiine_fread(bss.socket_fsa[client], &retsize, pBuffer, count, myhandle) == 0){
__os_snprintf(logbugger, sizeof(logbugger), "got %d",retsize);
if(DEBUG_LOG) log_string(bss.logsock, logbugger, BYTE_LOG_STR);
int fwrite = 0;
if((fwrite = my_FSWriteFile(pClient, pCmd, pBuffer,size,retsize,handle,0,0x0200)) >= 0){
__os_snprintf(logbugger, sizeof(logbugger), "wrote %d",retsize);
if(DEBUG_LOG) log_string(bss.logsock, logbugger, BYTE_LOG_STR);
}else{
__os_snprintf(logbugger, sizeof(logbugger), "my_FSWriteFile failed with error: %d",fwrite);
if(DEBUG_LOG) log_string(bss.logsock, logbugger, BYTE_LOG_STR);
log_string(bss.logsock, "error while FSWriteFile", BYTE_LOG_STR);
}
__os_snprintf(logbugger, sizeof(logbugger), "old p %d new p %d",pos,pos+retsize);
if(DEBUG_LOG) log_string(bss.logsock, logbugger, BYTE_LOG_STR);
pos += retsize;
}else{
log_string(bss.logsock, "error while recieving file", BYTE_LOG_STR);
break;
}
}
int result = 0;
if((cafiine_fclose(bss.socket_fsa[client], &result, myhandle,0)) == 0 && result == 0){
if(DEBUG_LOG) log_string(bss.logsock, "cafiine_fclose success", BYTE_LOG_STR);
}else{
log_string(bss.logsock, "cafiine_fclose failed", BYTE_LOG_STR);
}
log_string(bss.socket_fsa[client], "dumping common savedata", BYTE_LOG_STR);
dump_dir(pClient,client,pCmd,"/vol/save/common/",error,60);
log_string(bss.socket_fsa[client], "done!", BYTE_LOG_STR);
}else{
log_string(bss.logsock, "cafiine_fopen failed", BYTE_LOG_STR);
}
}
if((FSCloseFile (pClient, pCmd, handle, -1)) <= 0)
log_string(bss.logsock, "FSCloseFile failed", BYTE_LOG_STR);
}
}else if( type == BYTE_FOLDER){
__os_snprintf(logbugger, sizeof(logbugger), "dir: %s",namebuffer);
log_string(bss.logsock, logbugger, BYTE_LOG_STR);
if(DEBUG_LOG) log_string(bss.logsock, newpath, BYTE_LOG_STR);
if(FSMakeDir(pClient, pCmd, newpath, -1) == 0){
char op_offset[strlen(relativepath) + strlen(namebuffer)+ 1 + 1];
__os_snprintf(op_offset, sizeof(op_offset), "%s%s/",relativepath,namebuffer);
injectFiles(pClient, pCmd, newpath,op_offset,error);
}else{
log_string(bss.logsock, "folder creation failed", BYTE_LOG_STR);
}
}
}
free(pBuffer);
log_string(bss.logsock, "getting files done", BYTE_LOG_STR);
}
#define MAKE_MAGIC(x) { x, my_ ## x, &real_ ## x }
@ -270,5 +462,9 @@ struct magic_t {
MAKE_MAGIC(FSInit),
MAKE_MAGIC(FSShutdown),
MAKE_MAGIC(FSAddClientEx),
MAKE_MAGIC(FSDelClient),
MAKE_MAGIC(FSDelClient),
MAKE_MAGIC(FSWriteFile),
MAKE_MAGIC(FSFlushQuota),
};

View File

@ -2,6 +2,31 @@
#include "../common/fs_defs.h"
#define NULL ((void *)0)
#define BYTE_NORMAL 0xff
#define BYTE_SPECIAL 0xfe
#define BYTE_OPEN 0x00
#define BYTE_READ 0x01
#define BYTE_CLOSE 0x02
#define BYTE_OK 0x03
#define BYTE_SETPOS 0x04
#define BYTE_STATFILE 0x05
#define BYTE_EOF 0x06
#define BYTE_GETPOS 0x07
#define BYTE_REQUEST 0x08
#define BYTE_REQUEST_SLOW 0x09
#define BYTE_HANDLE 0x0A
#define BYTE_DUMP 0x0B
#define BYTE_PING 0x0C
#define BYTE_G_MODE 0x0D
#define BYTE_MODE_D 0x0E
#define BYTE_MODE_I 0x0F
#define BYTE_CLOSE_DUMP 0x10
#define BYTE_LOG_STR 0xfb
#define BYTE_FILE 0xC0
#define BYTE_FOLDER 0xC1
#define BYTE_GET_FILES 0xCC
#define BYTE_END 0xfd
void *memcpy(void *dst, const void *src, int bytes);
void *memset(void *dst, int val, int bytes);
@ -30,6 +55,8 @@ extern int connect(int socket, void *addr, int addrlen);
extern int send(int socket, const void *buffer, int size, int flags);
extern int recv(int socket, void *buffer, int size, int flags);
extern int __os_snprintf(char* s, int n, const char * format, ...);
int getFiles(int sock, char * path,char * resultname, int * resulttype,int *filesize);
void injectFiles(void *pClient, void *pCmd, char * path,char * relativepath, int error);
struct in_addr {
unsigned int s_addr;
@ -55,6 +82,7 @@ struct bss_t {
char save_path[255];
volatile int saveFolderChecked;
volatile int lock;
int logsock;
};
#define bss_ptr (*(struct bss_t **)0x100000e4)
@ -62,11 +90,12 @@ struct bss_t {
void cafiine_connect(int *socket);
void cafiine_disconnect(int socket);
int getMode(int sock, int * result);
int cafiine_fopen(int socket, int *result, const char *path, const char *mode, int *handle);
int cafiine_send_handle(int sock, int client, const char *path, int handle);
void cafiine_send_file(int sock, char *file, int size, int fd);
int cafiine_fread(int socket, int *result, void *buffer, int size, int count, int fd);
int cafiine_fclose(int socket, int *result, int fd);
int cafiine_fread(int socket, int *result, void *buffer, int size, int fd);
int cafiine_fclose(int socket, int *result, int fd, int dumpclose);
int cafiine_fsetpos(int socket, int *result, int fd, int set);
int cafiine_fgetpos(int socket, int *result, int fd, int *pos);
int cafiine_fstat(int sock, int *result, int fd, void *ptr);

View File

@ -1,33 +1,22 @@
#include "main.h"
static int recvwait(int sock, void *buffer, int len);
static int recvwaitlen(int sock, void *buffer, int len);
static int recvbyte(int sock);
static int sendwait(int sock, const void *buffer, int len);
static int sendbyte(int sock, unsigned char value);
static int cafiine_handshake(int sock);
#define CHECK_ERROR(cond) if (cond) { goto error; }
#define BYTE_NORMAL 0xff
#define BYTE_SPECIAL 0xfe
//#define BYTE_OPEN 0x00
//#define BYTE_READ 0x01
#define BYTE_CLOSE 0x02
//#define BYTE_OK 0x03
//#define BYTE_SETPOS 0x04
//#define BYTE_STATFILE 0x05
//#define BYTE_EOF 0x06
//#define BYTE_GETPOS 0x07
#define BYTE_REQUEST 0x08
#define BYTE_REQUEST_SLOW 0x09
#define BYTE_HANDLE 0x0A
#define BYTE_DUMP 0x0B
#define BYTE_PING 0x0C
#define BYTE_LOG_STR 0xfb
void GX2WaitForVsync(void);
void cafiine_connect(int *psock) {
extern unsigned int server_ip;
struct sockaddr_in addr;
@ -79,6 +68,56 @@ error:
return ret;
}
int getMode(int sock,int * result)
{
while (bss.lock) GX2WaitForVsync();
bss.lock = 1;
CHECK_ERROR(sock == -1);
int ret = 0;
// create and send buffer with : [cmd id][fd][size][buffer data ...]
{
ret = sendbyte(sock, BYTE_G_MODE);
// wait reply
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
if(ret == BYTE_MODE_D) *result = BYTE_MODE_D;
if(ret == BYTE_MODE_I) *result = BYTE_MODE_I;
ret = 1;
}
error:
bss.lock = 0;
return ret;
}
int cafiine_fsetpos(int sock, int *result, int fd, int set) {
while (bss.lock) GX2WaitForVsync();
bss.lock = 1;
CHECK_ERROR(sock == -1);
int ret;
char buffer[1 + 8];
buffer[0] = BYTE_SETPOS;
*(int *)(buffer + 1) = fd;
*(int *)(buffer + 5) = set;
ret = sendwait(sock, buffer, 1 + 8);
CHECK_ERROR(ret < 0);
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret == BYTE_NORMAL);
ret = recvwait(sock, result, 4);
CHECK_ERROR(ret < 0);
bss.lock = 0;
return 0;
error:
bss.lock = 0;
return -1;
}
int cafiine_send_handle(int sock, int client, const char *path, int handle)
{
@ -122,6 +161,49 @@ error:
bss.lock = 0;
return -1;
}
int cafiine_fopen(int sock, int *result, const char *path, const char *mode, int *handle) {
while (bss.lock) GX2WaitForVsync();
bss.lock = 1;
CHECK_ERROR(sock == -1);
int final_ret = 0;
int ret;
int len_path = 0;
while (path[len_path++]);
int len_mode = 0;
while (mode[len_mode++]);
//
{
char buffer[1 + 8 + len_path + len_mode];
buffer[0] = BYTE_OPEN;
*(int *)(buffer + 1) = len_path;
*(int *)(buffer + 5) = len_mode;
for (ret = 0; ret < len_path; ret++)
buffer[9 + ret] = path[ret];
for (ret = 0; ret < len_mode; ret++)
buffer[9 + len_path + ret] = mode[ret];
ret = sendwait(sock, buffer, 1 + 8 + len_path + len_mode);
}
CHECK_ERROR(ret < 0);
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret == BYTE_NORMAL);
ret = recvwait(sock, result, 4);
CHECK_ERROR(ret < 0);
ret = recvwait(sock, handle, 4);
CHECK_ERROR(ret < 0);
quit:
bss.lock = 0;
return final_ret;
error:
bss.lock = 0;
return -1;
}
void cafiine_send_file(int sock, char *file, int size, int fd) {
while (bss.lock) GX2WaitForVsync();
@ -153,10 +235,36 @@ error:
bss.lock = 0;
return;
}
int cafiine_fread(int sock, int *result, void *ptr, int size, int fd) {
while (bss.lock) GX2WaitForVsync();
bss.lock = 1;
CHECK_ERROR(sock == -1);
int ret;
char buffer[1 + 8];
buffer[0] = BYTE_READ;
*(int *)(buffer + 1) = size;
*(int *)(buffer + 5) = fd;
ret = sendwait(sock, buffer, 1 + 8);
ret = recvbyte(sock);
CHECK_ERROR(ret == BYTE_NORMAL);
int sz;
ret = recvwait(sock, &sz, 4);
ret = recvwaitlen(sock, ptr, sz);
*result = sz - ret;
ret = sendbyte(sock, BYTE_OK);
bss.lock = 0;
return 0;
error:
bss.lock = 0;
return -1;
}
int cafiine_fclose(int sock, int *result, int fd) {
int cafiine_fclose(int sock, int *result, int fd,int dumpclose) {
while (bss.lock) GX2WaitForVsync();
bss.lock = 1;
@ -165,11 +273,11 @@ int cafiine_fclose(int sock, int *result, int fd) {
int ret;
char buffer[1 + 4];
buffer[0] = BYTE_CLOSE;
if(dumpclose)buffer[0] = BYTE_CLOSE_DUMP;
*(int *)(buffer + 1) = fd;
ret = sendwait(sock, buffer, 1 + 4);
CHECK_ERROR(ret < 0);
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
ret = recvbyte(sock);
CHECK_ERROR(ret == BYTE_NORMAL);
ret = recvwait(sock, result, 4);
CHECK_ERROR(ret < 0);
@ -181,6 +289,55 @@ error:
return -1;
}
int getFiles(int sock, char * path,char * resultname, int * resulttype, int * filesize){
while (bss.lock) GX2WaitForVsync();
bss.lock = 1;
CHECK_ERROR(sock == -1);
int result = 0;
int ret;
// create and send buffer with : [cmd id][len_path][path][filesize]
{
int size = 0;
while (path[size++]);
char buffer[1+4+size];
buffer[0] = BYTE_GET_FILES;
*(int *)(buffer + 1) = size;
for (ret = 0; ret < size; ret++)
buffer[5 + ret] = path[ret];
// send buffer, wait for reply
ret = sendwait(sock, buffer, 1+4+size);
// wait reply
ret = recvbyte(sock);
CHECK_ERROR(ret != BYTE_OK);
ret = recvbyte(sock);
CHECK_ERROR(ret != BYTE_FILE && ret != BYTE_FOLDER);
*resulttype = ret;
size = 0;
ret = recvwait(sock, &size, 4);
CHECK_ERROR(ret < 0);
ret = recvwait(sock, resultname, size+1);
CHECK_ERROR(ret < 0);
size = 0;
ret = recvwait(sock, &size, 4);
CHECK_ERROR(ret < 0);
*filesize = size;
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret != BYTE_SPECIAL);
result = 1;
}
error:
bss.lock = 0;
return result;
}
void cafiine_send_ping(int sock, int val1, int val2) {
while (bss.lock) GX2WaitForVsync();
bss.lock = 1;
@ -211,6 +368,19 @@ static int recvwait(int sock, void *buffer, int len) {
error:
return ret;
}
static int recvwaitlen(int sock, void *buffer, int len) {
int ret;
while (len > 0) {
ret = recv(sock, buffer, len, 0);
CHECK_ERROR(ret < 0);
len -= ret;
buffer += ret;
}
return 0;
error:
return len;
}
static int recvbyte(int sock) {
unsigned char buffer[1];
@ -260,3 +430,9 @@ void log_string(int sock, const char* str, char flag_byte) {
bss.lock = 0;
}
static int sendbyte(int sock, unsigned char byte) {
unsigned char buffer[1];
buffer[0] = byte;
return sendwait(sock, buffer, 1);
}

View File

@ -35,7 +35,7 @@ PROVIDE(FSDelClient = 0x1068a08);
PROVIDE(FSOpenFile = 0x106ef7c);
PROVIDE(FSOpenFileAsync = 0x0106a434);
PROVIDE(FSInitCmdBlock = 0x01068c54);
PROVIDE(FSMakeDir = 0x0106f8e0);
PROVIDE(FSCloseFile = 0x106f088);
PROVIDE(FSReadFile = 0x106f108);
PROVIDE(FSReadFileWithPos = 0x106f194);
@ -43,6 +43,9 @@ PROVIDE(FSGetPosFile = 0x106f4c0);
PROVIDE(FSSetPosFile = 0x106f530);
PROVIDE(FSGetStatFile = 0x106f5a0);
PROVIDE(FSIsEof = 0x106f610);
PROVIDE(FSWriteFile = 0x106F228);
PROVIDE(FSFlushQuota = 0x106FAC8);
/* */
PROVIDE(FSGetStat = 0x0106fdc8);
@ -54,7 +57,7 @@ PROVIDE(FSReadDir = 0x0106f780);
PROVIDE(FSCloseDir = 0x0106f700);
PROVIDE(FSChangeDir = 0x0106eefc);
PROVIDE(FSCloseDir = 0x0106f700);
PROVIDE(FSRemove = 0x0106F960);
/* GX2 methods */
PROVIDE(GX2WaitForVsync = 0x1151964);
@ -65,7 +68,7 @@ PROVIDE(socket = 0x10c21c8);
PROVIDE(socketclose = 0x10c2314);
PROVIDE(connect = 0x10c0828);
PROVIDE(send = 0x10c16ac);
PROVIDE(recv = 0x10c0aec);
PROVIDE(recv = 0x10c0aec);
/* Standard library methods */
PROVIDE(memcpy = 0x1035a68);

Binary file not shown.

Binary file not shown.

View File

@ -13,11 +13,11 @@ namespace saviine_server
{
public const byte BYTE_NORMAL = 0xff;
public const byte BYTE_SPECIAL = 0xfe;
//public const byte BYTE_OPEN = 0x00;
// public const byte BYTE_READ = 0x01;
public const byte BYTE_OPEN = 0x00;
public const byte BYTE_READ = 0x01;
public const byte BYTE_CLOSE = 0x02;
//public const byte BYTE_OK = 0x03;
//public const byte BYTE_SETPOS = 0x04;
public const byte BYTE_OK = 0x03;
public const byte BYTE_SETPOS = 0x04;
//public const byte BYTE_STATFILE = 0x05;
//public const byte BYTE_EOF = 0x06;
//public const byte BYTE_GETPOS = 0x07;
@ -26,8 +26,15 @@ namespace saviine_server
public const byte BYTE_HANDLE = 0x0A;
public const byte BYTE_DUMP = 0x0B;
public const byte BYTE_PING = 0x0C;
public const byte BYTE_G_MODE = 0x0D;
public const byte BYTE_MODE_D = 0x0E;
public const byte BYTE_MODE_I = 0x0F;
public const byte BYTE_CLOSE_DUMP = 0x10;
public const byte BYTE_LOG_STR = 0xFB;
public const byte BYTE_FILE = 0xC0;
public const byte BYTE_FOLDER = 0xC1;
public const byte BYTE_GET_FILES = 0xCC;
public const byte BYTE_END = 0xfd;
[Flags]
public enum FSStatFlag : uint
@ -75,6 +82,7 @@ namespace saviine_server
const uint BUFFER_SIZE = 64 * 1024;
static Boolean fastmode = false;
static byte op_mode = BYTE_MODE_D;
static void Main(string[] args)
{
if (args.Length > 1)
@ -86,11 +94,36 @@ namespace saviine_server
{
if (args[0].Equals("fastmode") || args[0].Equals("fast") || args[0].Equals("-fast"))
{
fastmode = true;
Console.WriteLine("Now using fastmode");
op_mode = BYTE_MODE_D;
fastmode = true;
}else if(args[0].Equals("inject")) {
op_mode = BYTE_MODE_I;
}
}
if (args.Length == 2)
{
if (args[0].Equals("dump")) {
op_mode = BYTE_MODE_D;
if (args[1].Equals("fastmode") || args[1].Equals("fast") || args[1].Equals("-fast"))
{
fastmode = true;
}
}else if(args[0].Equals("inject")) {
op_mode = BYTE_MODE_I;
}
}
if (op_mode == BYTE_MODE_D)
{
Console.WriteLine("Dump mode");
if(fastmode)Console.WriteLine("Now using fastmode");
}
else if(op_mode == BYTE_MODE_I)
{
Console.WriteLine("Injection mode!");
}
// Check for cafiine_root and logs folder
if (!Directory.Exists(root))
{
@ -149,6 +182,21 @@ namespace saviine_server
log.Flush();
Console.Write(str);
}
public static int countDirectory(string targetDirectory)
{
int x = 0;
// Process the list of files found in the directory.
string [] fileEntries = Directory.GetFiles(targetDirectory);
foreach(string fileName in fileEntries)
x++;
// Recurse into subdirectories of this directory.
string [] subdirectoryEntries = Directory.GetDirectories(targetDirectory);
foreach(string subdirectory in subdirectoryEntries)
x++;
return x;
}
static void Handle(object client_obj)
{
@ -156,6 +204,8 @@ namespace saviine_server
FileStream[] files = new FileStream[256];
Dictionary<int, FileStream> files_request = new Dictionary<int, FileStream>();
StreamWriter log = null;
Dictionary<string, Dictionary<string, byte>> dir_files = new Dictionary<string, Dictionary<string, byte>>();
try
{
@ -196,23 +246,231 @@ namespace saviine_server
while (true)
{
byte cmd_byte = reader.ReadByte();
//Log(log, "cmd_byte");
byte cmd_byte = reader.ReadByte();
switch (cmd_byte)
{
case BYTE_HANDLE:
{
case BYTE_OPEN:
{
//Log(log, "BYTE_OPEN");
bool request_slow = false;
int len_path = reader.ReadInt32();
int len_mode = reader.ReadInt32();
string path = reader.ReadString(Encoding.ASCII, len_path - 1);
if (reader.ReadByte() != 0) throw new InvalidDataException();
string mode = reader.ReadString(Encoding.ASCII, len_mode - 1);
if (reader.ReadByte() != 0) throw new InvalidDataException();
if (File.Exists(LocalRoot + path))
{
int handle = -1;
for (int i = 1; i < files.Length; i++)
{
if (files[i] == null)
{
handle = i;
break;
}
}
if (handle == -1)
{
Log(log, name + " Out of file handles!");
writer.Write(BYTE_SPECIAL);
writer.Write(-19);
writer.Write(0);
break;
}
//Log(log, name + " -> fopen(\"" + path + "\", \"" + mode + "\") = " + handle.ToString());
files[handle] = new FileStream(LocalRoot + path, FileMode.Open, FileAccess.Read, FileShare.Read);
writer.Write(BYTE_SPECIAL);
writer.Write(0);
writer.Write(handle);
}
else { writer.Write(BYTE_NORMAL); }
// Log(log, "No request found: " + LocalRoot + path);
break;
}
case BYTE_SETPOS:
{
//Log(log, "BYTE_SETPOS");
int fd = reader.ReadInt32();
int pos = reader.ReadInt32();
if ((fd & 0x0fff00ff) == 0x0fff00ff)
{
int handle = (fd >> 8) & 0xff;
if (files[handle] == null)
{
writer.Write(BYTE_SPECIAL);
writer.Write(-38);
break;
}
FileStream f = files[handle];
Log(log, "Postion was set to " + pos + "for handle " + handle);
f.Position = pos;
writer.Write(BYTE_SPECIAL);
writer.Write(0);
}
else
{
writer.Write(BYTE_NORMAL);
}
break;
}
case BYTE_GET_FILES:
{
int len_path = reader.ReadInt32();
string path = reader.ReadString(Encoding.ASCII, len_path-1);
if (reader.ReadByte() != 0) throw new InvalidDataException();
int x = 0;
if (path[0] == '/' && path[1] == '/')
{
path = path.Substring(2);
}
else if (path[0] == '/')
{
path = path.Substring(1);
}
path = LocalRoot + path;
if(Directory.Exists(path)) {
x = countDirectory(path);
if (x > 0)
{
Dictionary<string, byte> value;
if (!dir_files.TryGetValue(path, out value))
{
//Console.Write("found no \"" + path + "\" in dic \n");
value = new Dictionary<string, byte>();
string[] fileEntries = Directory.GetFiles(path);
foreach (string fn in fileEntries)
{
string fileName = Path.GetFileName(fn);
value.Add(fileName, BYTE_FILE);
}
string[] subdirectoryEntries = Directory.GetDirectories(path);
foreach (string sd in subdirectoryEntries)
{
string subdirectory = Path.GetFileName(sd);
value.Add(subdirectory, BYTE_FOLDER);
}
dir_files.Add(path, value);
//Console.Write("added \"" + path + "\" to dic \n");
}
else
{
//Console.Write("dic for \"" + path + "\" ready \n");
}
if (value.Count > 0)
{
writer.Write(BYTE_OK);
//Console.Write("sent ok byte \n");
foreach (var item in value)
{ //Write
writer.Write(item.Value);
//Console.Write("type : " + item.Value);
writer.Write(item.Key.Length);
//Console.Write("length : " + item.Key.Length);
writer.Write(item.Key, Encoding.ASCII, true);
//Console.Write("filename : " + item.Key);
int length = 0;
if (item.Value == BYTE_FILE) length = (int)new System.IO.FileInfo(path + "/" + item.Key).Length;
writer.Write(length);
//Console.Write("filesize : " + length + " \n");
value.Remove(item.Key);
//Console.Write("removed from list! " + value.Count + " remaining\n");
break;
}
writer.Write(BYTE_SPECIAL); //
//Console.Write("file sent, wrote special byte \n");
}
else
{
writer.Write(BYTE_END); //
//Console.Write("list was empty return BYTE_END \n");
dir_files.Remove(path);
//Console.Write("removed \"" + path + "\" from dic \n");
}
}
else
{
//Console.Write(path + "empty \n");
writer.Write(BYTE_END); //
}
}
else
{
//Console.Write(path + " is not found\n");
writer.Write(BYTE_END); //
}
//Console.Write("in break \n");
break;
}
case BYTE_READ:
{
//Log(log,"BYTE_READ");
int size = reader.ReadInt32();
int fd = reader.ReadInt32();
FileStream f = files[fd];
byte[] buffer = new byte[size];
int sz = (int)f.Length;
int rd = 0;
//Log(log, "want size:" + size + " for handle: " + fd);
writer.Write(BYTE_SPECIAL);
rd = f.Read(buffer, 0, buffer.Length);
//Log(log,"rd:" + rd);
writer.Write(rd);
writer.Write(buffer, 0, rd);
int offset = (int)f.Position;
int progress = (int)(((float)offset / (float)sz) * 100);
string strProgress = progress.ToString().PadLeft(3, ' ');
string strSize = (sz / 1024).ToString();
string strCurrent = (offset / 1024).ToString().PadLeft(strSize.Length, ' ');
Console.Write("\r\t--> {0}% ({1} kB / {2} kB)", strProgress, strCurrent, strSize);
log.Write("\r\t--> {0}% ({1} kB / {2} kB)", strProgress, strCurrent, strSize);
//Console.Write("send " + rd );
if(offset == sz) Console.Write("\n");
int ret = -5;
if ((ret =reader.ReadByte()) != BYTE_OK)
{
Console.Write("error, got " + ret + " instead of " + BYTE_OK);
//throw new InvalidDataException();
}
//Log(log, "break READ");
break;
}
case BYTE_HANDLE:
{
//Log(log,"BYTE_HANDLE");
// Read buffer params : fd, path length, path string
int fd = reader.ReadInt32();
int len_path = reader.ReadInt32();
string path = reader.ReadString(Encoding.ASCII, len_path - 1);
if (reader.ReadByte() != 0) throw new InvalidDataException();
if (!Directory.Exists(LocalRoot + path))
if (!Directory.Exists(LocalRoot + "dump" + path))
{
Directory.CreateDirectory(Path.GetDirectoryName(LocalRoot + path));
Directory.CreateDirectory(Path.GetDirectoryName(LocalRoot + "dump" + path));
}
// Add new file for incoming data
files_request.Add(fd, new FileStream(LocalRoot + path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write));
files_request.Add(fd, new FileStream(LocalRoot + "dump" + path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write));
// Send response
if (fastmode) {
writer.Write(BYTE_REQUEST);
@ -227,7 +485,8 @@ namespace saviine_server
break;
}
case BYTE_DUMP:
{
{
//Log(log,"BYTE_DUMP");
// Read buffer params : fd, size, file data
int fd = reader.ReadInt32();
int sz = reader.ReadInt32();
@ -257,25 +516,31 @@ namespace saviine_server
}
case BYTE_CLOSE:
{
//Log(log, "BYTE_CLOSE");
int fd = reader.ReadInt32();
if ((fd & 0x0fff00ff) == 0x0fff00ff)
if (files[fd] == null)
{
int handle = (fd >> 8) & 0xff;
if (files[handle] == null)
{
writer.Write(BYTE_SPECIAL);
writer.Write(-38);
break;
}
Log(log, name + " close(" + handle.ToString() + ")");
FileStream f = files[handle];
writer.Write(BYTE_SPECIAL);
writer.Write(0);
f.Close();
files[handle] = null;
writer.Write(-38);
break;
}
else
//Log(log, name + " close(" + fd.ToString() + ")");
FileStream f = files[fd];
writer.Write(BYTE_SPECIAL);
writer.Write(0);
f.Close();
files[fd] = null;
break;
}
case BYTE_CLOSE_DUMP:
{
int fd = reader.ReadInt32();
if ((fd & 0x0fff00ff) != 0x0fff00ff)
{
// Check if it is a file to dump
foreach (var item in files_request)
@ -291,7 +556,6 @@ namespace saviine_server
// Close file and remove from request list
dump_file.Close();
files_request.Remove(fd);
break;
}
}
@ -300,18 +564,32 @@ namespace saviine_server
writer.Write(BYTE_NORMAL);
}
break;
}
}
case BYTE_PING:
{
//Log(log, "BYTE_PING");
int val1 = reader.ReadInt32();
int val2 = reader.ReadInt32();
Log(log, name + " PING RECEIVED with values : " + val1.ToString() + " - " + val2.ToString());
break;
}
case BYTE_G_MODE:
{
if (op_mode == BYTE_MODE_D)
{
writer.Write(BYTE_MODE_D);
}
else if (op_mode == BYTE_MODE_I)
{
writer.Write(BYTE_MODE_I);
}
break;
}
case BYTE_LOG_STR:
{
//Log(log, "BYTE_LOG_STR");
int len_str = reader.ReadInt32();
string str = reader.ReadString(Encoding.ASCII, len_str - 1);
if (reader.ReadByte() != 0) throw new InvalidDataException();
@ -320,6 +598,7 @@ namespace saviine_server
break;
}
default:
Log(log, "xx" + cmd_byte);
throw new InvalidDataException();
}
}

View File

@ -0,0 +1 @@
saviine_server.exe dump

View File

@ -0,0 +1 @@
saviine_server.exe inject

Binary file not shown.