static inline bool do_check64 (size_t i, const Elf64_auxv_t (*a64)[], uint_fast8_t *elfdata) { /* The AUXV pointer might not even be naturally aligned for 64-bit data, because note payloads in a core file are not aligned. */ uint64_t type = read_8ubyte_unaligned_noncvt (&(*a64)[i].a_type); uint64_t val = read_8ubyte_unaligned_noncvt (&(*a64)[i].a_un.a_val); if (type == BE64 (PROBE_TYPE) && val == BE64 (PROBE_VAL64)) { *elfdata = ELFDATA2MSB; return true; } if (type == LE64 (PROBE_TYPE) && val == LE64 (PROBE_VAL64)) { *elfdata = ELFDATA2LSB; return true; } return false; }
void logResponseVerbose(const char *const ePID, const BYTE *const hwid, const RESPONSE *const response, const PRINTFUNC p) { char guidBuffer[GUID_STRING_LENGTH + 1]; //SYSTEMTIME st; p("Protocol version : %u.%u\n", (uint32_t)LE16(response->MajorVer), (uint32_t)LE16(response->MinorVer)); p("KMS host extended PID : %s\n", ePID); if (LE16(response->MajorVer) > 5) # ifndef _WIN32 p("KMS host Hardware ID : %016llX\n", (unsigned long long)BE64(*(uint64_t*)hwid)); # else // _WIN32 p("KMS host Hardware ID : %016I64X\n", (unsigned long long)BE64(*(uint64_t*)hwid)); # endif // WIN32 uuid2StringLE(&response->CMID, guidBuffer); p("Client machine ID : %s\n", guidBuffer); char mbstr[64]; time_t st; st = fileTimeToUnixTime(&response->ClientTime); strftime(mbstr, sizeof(mbstr), "%Y-%m-%d %X", gmtime(&st)); p("Client request timestamp (UTC) : %s\n", mbstr); p("KMS host current active clients : %u\n", (uint32_t)LE32(response->Count)); p("Renewal interval policy : %u\n", (uint32_t)LE32(response->VLRenewalInterval)); p("Activation interval policy : %u\n", (uint32_t)LE32(response->VLActivationInterval)); }
/* Examine an auxv data block and determine its format. Return true iff we figured it out. */ static bool auxv_format_probe (const void *auxv, size_t size, uint_fast8_t *elfclass, uint_fast8_t *elfdata) { const union { char buf[size]; Elf32_auxv_t a32[size / sizeof (Elf32_auxv_t)]; Elf64_auxv_t a64[size / sizeof (Elf64_auxv_t)]; } *u = auxv; inline bool check64 (size_t i) { /* The AUXV pointer might not even be naturally aligned for 64-bit data, because note payloads in a core file are not aligned. */ uint64_t type = read_8ubyte_unaligned_noncvt (&u->a64[i].a_type); uint64_t val = read_8ubyte_unaligned_noncvt (&u->a64[i].a_un.a_val); if (type == BE64 (PROBE_TYPE) && val == BE64 (PROBE_VAL64)) { *elfdata = ELFDATA2MSB; return true; } if (type == LE64 (PROBE_TYPE) && val == LE64 (PROBE_VAL64)) { *elfdata = ELFDATA2LSB; return true; } return false; }
void DecryptBufferLRW64 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo) { /* Deprecated/legacy */ int cipher = EAGetFirstCipher (cryptoInfo->ea); unsigned __int8 *p = buffer; unsigned __int8 *ks = cryptoInfo->ks; unsigned __int8 i[8]; unsigned __int8 t[8]; unsigned __int64 b; *(unsigned __int64 *)i = BE64(blockIndex); if (length % 8) GST_THROW_FATAL_EXCEPTION; for (b = 0; b < length >> 3; b++) { Gf64MulTab (i, t, &cryptoInfo->gf_ctx); Xor64 ((unsigned __int64 *)p, (unsigned __int64 *)t); DecipherBlock (cipher, p, ks); Xor64 ((unsigned __int64 *)p, (unsigned __int64 *)t); p += 8; if (i[7] != 0xff) i[7]++; else *(unsigned __int64 *)i = BE64 ( BE64(*(unsigned __int64 *)i) + 1 ); } FAST_ERASE64 (t, sizeof(t)); }
void DecryptBufferLRW128 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo) { /* Deprecated/legacy */ int cipher = EAGetFirstCipher (cryptoInfo->ea); int cipherCount = EAGetCipherCount (cryptoInfo->ea); unsigned __int8 *p = buffer; unsigned __int8 *ks = cryptoInfo->ks; unsigned __int8 i[8]; unsigned __int8 t[16]; unsigned __int64 b; *(unsigned __int64 *)i = BE64(blockIndex); if (length % 16) GST_THROW_FATAL_EXCEPTION; // Note that the maximum supported volume size is 8589934592 GB (i.e., 2^63 bytes). for (b = 0; b < length >> 4; b++) { Gf128MulBy64Tab (i, t, &cryptoInfo->gf_ctx); Xor128 ((unsigned __int64 *)p, (unsigned __int64 *)t); if (cipherCount > 1) { // Cipher cascade ks = cryptoInfo->ks + EAGetKeyScheduleSize (cryptoInfo->ea); for (cipher = EAGetLastCipher (cryptoInfo->ea); cipher != 0; cipher = EAGetPreviousCipher (cryptoInfo->ea, cipher)) { ks -= CipherGetKeyScheduleSize (cipher); DecipherBlock (cipher, p, ks); } } else { DecipherBlock (cipher, p, ks); } Xor128 ((unsigned __int64 *)p, (unsigned __int64 *)t); p += 16; if (i[7] != 0xff) i[7]++; else *(unsigned __int64 *)i = BE64 ( BE64(*(unsigned __int64 *)i) + 1 ); } FAST_ERASE64 (t, sizeof(t)); }
int dme_read_unit_desc(struct ufs_dev *dev, uint8_t index) { STACKBUF_DMA_ALIGN(unit_desc, sizeof(struct ufs_unit_desc)); struct ufs_unit_desc *desc = (struct ufs_unit_desc *) unit_desc; struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR, UFS_DESC_IDN_UNIT, index, 0, (addr_t) unit_desc, sizeof(struct ufs_unit_desc)}; if (dme_send_query_upiu(dev, &query)) { dprintf(CRITICAL, "%s:%d DME Read Unit Descriptor request failed\n", __func__, __LINE__); return -UFS_FAILURE; } /* Flush buffer. */ arch_invalidate_cache_range((addr_t) desc, sizeof(struct ufs_unit_desc)); dev->lun_cfg[index].logical_blk_cnt = BE64(desc->logical_blk_cnt); dev->lun_cfg[index].erase_blk_size = BE32(desc->erase_blk_size); // use only the lower 32 bits for rpmb partition size if (index == UFS_WLUN_RPMB) dev->rpmb_num_blocks = BE32(desc->logical_blk_cnt >> 32); return UFS_SUCCESS; }
UINT64_STRUCT GetHeaderField64 (byte *header, int offset) { UINT64_STRUCT uint64Struct; #ifndef TC_NO_COMPILER_INT64 uint64Struct.Value = BE64 (*(uint64 *) (header + offset)); #else uint64Struct.HighPart = BE32 (*(uint32 *) (header + offset)); uint64Struct.LowPart = BE32 (*(uint32 *) (header + offset + 4)); #endif return uint64Struct; }
/** Terminate the hash to get the digest */ void _stdcall sha512_done(sha512_ctx *ctx, unsigned char *out) { int i; /* increase the length of the message */ ctx->length += ctx->curlen * 8; /* append the '1' bit */ ctx->buf[ctx->curlen++] = 0x80; /* if the length is currently above 112 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (ctx->curlen > 112) { while (ctx->curlen < SHA512_BLOCK_SIZE) { ctx->buf[ctx->curlen++] = 0; } sha512_compress(ctx, ctx->buf); ctx->curlen = 0; } /* pad upto 120 bytes of zeroes * note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash * > 2^64 bits of data... :-) */ while (ctx->curlen < 120) { ctx->buf[ctx->curlen++] = 0; } /* store length */ p64(ctx->buf)[15] = BE64(ctx->length); sha512_compress(ctx, ctx->buf); /* copy output */ for (i = 0; i < 8; i++) { p64(out)[i] = BE64(ctx->hash[i]); } }
static int process_read_file_cmd(client_t *client, netiso_read_file_cmd *cmd) { uint64_t offset; uint32_t remaining; int32_t bytes_read; netiso_read_file_result result; offset = BE64(cmd->offset); remaining = BE32(cmd->num_bytes); if (!client->ro_file) { bytes_read = -1; goto send_result; } if (remaining > BUFFER_SIZE) { bytes_read = -1; goto send_result; } if (client->ro_file->seek(offset, SEEK_SET) < 0) { bytes_read = -1; goto send_result; } bytes_read = client->ro_file->read(client->buf, remaining); if (bytes_read < 0) { bytes_read = -1; } send_result: result.bytes_read = (int32_t)BE32(bytes_read); if (send(client->s, (char *)&result, sizeof(result), 0) != 4) { DPRINTF("send failed on send result (read file)\n"); return -1; } if (bytes_read > 0 && send(client->s, (char *)client->buf, bytes_read, 0) != bytes_read) { DPRINTF("send failed on read file!\n"); return -1; } return 0; }
static int process_read_file_critical(client_t *client, netiso_read_file_critical_cmd *cmd) { uint64_t offset; uint32_t remaining; offset = BE64(cmd->offset); remaining = BE32(cmd->num_bytes); if (!client->ro_file) return -1; #ifdef WIN32 DPRINTF("Read %I64x %x\n", (long long unsigned int)offset, remaining); #else DPRINTF("Read %llx %x\n", (long long unsigned int)offset, remaining); #endif if (client->ro_file->seek(offset, SEEK_SET) < 0) { DPRINTF("seek_file failed!\n"); return -1; } while (remaining > 0) { uint32_t read_size; if (remaining < BUFFER_SIZE) { read_size = remaining; } else { read_size = BUFFER_SIZE; } if (client->ro_file->read(client->buf, read_size) != read_size) { DPRINTF("read_file failed on read file critical command!\n"); return -1; } if (send(client->s, (char *)client->buf, read_size, 0) != read_size) { DPRINTF("send failed on read file critical command!\n"); return -1; } remaining -= read_size; } return 0; }
int ucs_do_scsi_unmap(struct ufs_dev *dev, struct scsi_unmap_req *req) { STACKBUF_DMA_ALIGN(cdb_param, SCSI_CDB_PARAM_LEN); STACKBUF_DMA_ALIGN(param, sizeof(struct unmap_param_list)); struct scsi_req_build_type req_upiu; struct unmap_param_list *param_list; struct unmap_blk_desc *blk_desc; param_list = (struct unmap_param_list *)param; param_list->data_len = (sizeof(struct unmap_param_list) - 1) << 0x8; /* n-1 */ param_list->blk_desc_data_len = sizeof(struct unmap_blk_desc) << 0x8; blk_desc = &(param_list->blk_desc); blk_desc->lba = BE64(req->start_lba); blk_desc->num_blks = BE32(req->num_blocks); memset((void*)cdb_param, 0, SCSI_CDB_PARAM_LEN); cdb_param[0] = SCSI_CMD_UNMAP; cdb_param[1] = 0; /*ANCHOR = 0 for UFS*/ cdb_param[6] = 0; /*Group No = 0*/ cdb_param[7] = 0; /* Param list length is 1, we erase 1 contiguous blk*/ cdb_param[8] = sizeof(struct unmap_param_list); cdb_param[9] = 0; /* Flush cdb to memory. */ dsb(); arch_invalidate_cache_range((addr_t) cdb_param, SCSI_CDB_PARAM_LEN); memset((void*)&req_upiu, 0 , sizeof(struct scsi_req_build_type)); req_upiu.cdb = (addr_t) cdb_param; req_upiu.data_buffer_addr = (addr_t) param; req_upiu.data_len = sizeof(struct unmap_param_list); req_upiu.flags = UPIU_FLAGS_WRITE; req_upiu.lun = req->lun; req_upiu.dd = UTRD_SYSTEM_TO_TARGET; if (ucs_do_scsi_cmd(dev, &req_upiu)) { dprintf(CRITICAL, "Failed to send SCSI unmap command \n"); return -UFS_FAILURE; } /* Flush buffer. */ arch_invalidate_cache_range((addr_t) param, SCSI_INQUIRY_LEN); return UFS_SUCCESS; }
void uuid2StringLE(const GUID *const guid, char *const string) { sprintf(string, # ifdef _WIN32 "%08x-%04x-%04x-%04x-%012I64x", # else "%08x-%04x-%04x-%04x-%012llx", # endif (unsigned int)LE32(guid->Data1), (unsigned int)LE16(guid->Data2), (unsigned int)LE16(guid->Data3), (unsigned int)BE16(*(uint16_t*)guid->Data4), (unsigned long long)BE64(*(uint64_t*)(guid->Data4)) & 0xffffffffffffLL ); }
static int process_get_dir_size_cmd(client_t *client, netiso_get_dir_size_cmd *cmd) { netiso_get_dir_size_result result; char *dirpath; uint16_t dp_len; int ret; dp_len = BE16(cmd->dp_len); dirpath = (char *)malloc(dp_len+1); if (!dirpath) { DPRINTF("CRITICAL: memory allocation error\n"); return -1; } dirpath[dp_len] = 0; ret = recv_all(client->s, (char *)dirpath, dp_len); if (ret != dp_len) { DPRINTF("recv failed, getting dirname for get_dir_size: %d %d\n", ret, get_network_error()); free(dirpath); return -1; } dirpath = translate_path(dirpath, 1, 1, NULL); if (!dirpath) { DPRINTF("Path cannot be translated. Connection with this client will be aborted.\n"); return -1; } DPRINTF("get_dir_size %s\n", dirpath); result.dir_size = BE64(calculate_directory_size(dirpath)); free(dirpath); ret = send(client->s, (char *)&result, sizeof(result), 0); if (ret != sizeof(result)) { DPRINTF("get_dir_size, send result error: %d %d\n", ret, get_network_error()); return -1; } return 0; }
/* compress 1024-bits */ static void sha512_compress(sha512_ctx *ctx, const unsigned char *buf) { u64 S[8], W[80], t0, t1; int i; /* copy state into S */ memcpy(S, ctx->hash, sizeof(S)); /* copy the state into 1024-bits into W[0..15] */ for (i = 0; i < 16; i++) { W[i] = BE64(p64(buf)[i]); } /* fill W[16..79] */ for (i = 16; i < 80; i++) { W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; } /* Compress */ #define RND(a,b,c,d,e,f,g,h,i) \ t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ t1 = Sigma0(a) + Maj(a, b, c); \ d += t0; \ h = t0 + t1; for (i = 0; i < 80; i += 8) { RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0); RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1); RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2); RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3); RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4); RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5); RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6); RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); } ctx->hash[0] += S[0]; ctx->hash[1] += S[1]; ctx->hash[2] += S[2]; ctx->hash[3] += S[3]; ctx->hash[4] += S[4]; ctx->hash[5] += S[5]; ctx->hash[6] += S[6]; ctx->hash[7] += S[7]; /* prevent leaks */ burn(&S, sizeof(S)); burn(&W, sizeof(W)); }
/** * parse_vblk_part - parse a LDM database vblk partition record * @buffer: vblk partition record loaded from the LDM database * @buf_size: size of @buffer in bytes * @vb: in memory vblk structure to return parsed information in * * This parses the LDM database vblk record of type VBLK_PART, i.e. a partition * record, supplied in @buffer and sets up the in memory vblk structure @vb * with the obtained information. * * Return 1 on success and -1 on error, in which case @vb is undefined. */ static int parse_vblk_part(const u8 *buffer, const int buf_size, struct vblk *vb) { int err, rel_objid, rel_name, rel_size, rel_parent; if (0x34 >= buf_size) return -1; /* Calculate relative offsets. */ rel_objid = 1 + buffer[0x18]; if (0x18 + rel_objid >= buf_size) return -1; rel_name = 1 + buffer[0x18 + rel_objid] + rel_objid; if (0x34 + rel_name >= buf_size) return -1; rel_size = 1 + buffer[0x34 + rel_name] + rel_name; if (0x34 + rel_size >= buf_size) return -1; rel_parent = 1 + buffer[0x34 + rel_size] + rel_size; if (0x34 + rel_parent >= buf_size) return -1; /* Setup @vb. */ vb->vblk_type = VBLK_PART; vb->obj_id = get_vnum(buffer + 0x18, &err); if (err || 0x34 + rel_parent + buffer[0x34 + rel_parent] >= buf_size) return -1; vb->disk_id = get_vnum(buffer + 0x34 + rel_parent, &err); if (err || 0x24 + rel_name + 8 > buf_size) return -1; vb->start_sector = BE64(buffer + 0x24 + rel_name); if (0x34 + rel_name + buffer[0x34 + rel_name] >= buf_size) return -1; vb->num_sectors = get_vnum(buffer + 0x34 + rel_name, &err); if (err || 0x18 + rel_objid + buffer[0x18 + rel_objid] >= buf_size) return -1; err = get_vstr(buffer + 0x18 + rel_objid, vb->name, sizeof(vb->name)); if (err == -1) return err; ldm_debug("Parsed Partition VBLK successfully.\n"); return 1; }
static void Sha256Finish(Sha256Ctx *Ctx, BYTE *hash) { unsigned int i, b_len = Ctx->Len & 63; Ctx->Buffer[ b_len ] = 0x80; if ( b_len ^ 63 ) memset(Ctx->Buffer + b_len + 1, 0, b_len ^ 63); if ( b_len >= 56 ) { Sha256ProcessBlock(Ctx, Ctx->Buffer); memset(Ctx->Buffer, 0, 56); } //PUT_UAA64BE(Ctx->Buffer, (unsigned long long)(Ctx->Len * 8), 7); ((uint64_t*)Ctx->Buffer)[7] = BE64((uint64_t)Ctx->Len << 3); Sha256ProcessBlock(Ctx, Ctx->Buffer); for (i = 0; i < 8; i++) //PUT_UAA32BE(hash, Ctx->State[i], i); ((DWORD*)hash)[i] = BE32(Ctx->State[i]); }
/* Examine an auxv data block and determine its format. Return true iff we figured it out. */ static bool auxv_format_probe (const void *auxv, size_t size, uint_fast8_t *elfclass, uint_fast8_t *elfdata) { const union { char buf[size]; Elf32_auxv_t a32[size / sizeof (Elf32_auxv_t)]; Elf64_auxv_t a64[size / sizeof (Elf64_auxv_t)]; } *u = auxv; inline bool check64 (size_t i) { if (u->a64[i].a_type == BE64 (PROBE_TYPE) && u->a64[i].a_un.a_val == BE64 (PROBE_VAL64)) { *elfdata = ELFDATA2MSB; return true; } if (u->a64[i].a_type == LE64 (PROBE_TYPE) && u->a64[i].a_un.a_val == LE64 (PROBE_VAL64)) { *elfdata = ELFDATA2LSB; return true; } return false; } inline bool check32 (size_t i) { if (u->a32[i].a_type == BE32 (PROBE_TYPE) && u->a32[i].a_un.a_val == BE32 (PROBE_VAL32)) { *elfdata = ELFDATA2MSB; return true; } if (u->a32[i].a_type == LE32 (PROBE_TYPE) && u->a32[i].a_un.a_val == LE32 (PROBE_VAL32)) { *elfdata = ELFDATA2LSB; return true; } return false; } for (size_t i = 0; i < size / sizeof (Elf64_auxv_t); ++i) { if (check64 (i)) { *elfclass = ELFCLASS64; return true; } if (check32 (i * 2) || check32 (i * 2 + 1)) { *elfclass = ELFCLASS32; return true; } } return false; }
static int report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata, Dwfl *dwfl, GElf_Addr r_debug_vaddr, Dwfl_Memory_Callback *memory_callback, void *memory_callback_arg) { /* Skip r_version, to aligned r_map field. */ GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass); void *buffer = NULL; size_t buffer_available = 0; inline int release_buffer (int result) { if (buffer != NULL) (void) (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0, memory_callback_arg); return result; } GElf_Addr addrs[4]; inline bool read_addrs (GElf_Addr vaddr, size_t n) { size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read. */ /* Read a new buffer if the old one doesn't cover these words. */ if (buffer == NULL || vaddr < read_vaddr || vaddr - read_vaddr + nb > buffer_available) { release_buffer (0); read_vaddr = vaddr; int segndx = INTUSE(dwfl_addrsegment) (dwfl, vaddr, NULL); if (unlikely (segndx < 0) || unlikely (! (*memory_callback) (dwfl, segndx, &buffer, &buffer_available, vaddr, nb, memory_callback_arg))) return true; } const union { Elf32_Addr a32[n]; Elf64_Addr a64[n]; } *in = vaddr - read_vaddr + buffer; if (elfclass == ELFCLASS32) { if (elfdata == ELFDATA2MSB) for (size_t i = 0; i < n; ++i) addrs[i] = BE32 (in->a32[i]); else for (size_t i = 0; i < n; ++i) addrs[i] = LE32 (in->a32[i]); } else { if (elfdata == ELFDATA2MSB) for (size_t i = 0; i < n; ++i) addrs[i] = BE64 (in->a64[i]); else for (size_t i = 0; i < n; ++i) addrs[i] = LE64 (in->a64[i]); } return false; }
static int process_read_dir_entry_cmd(client_t *client, netiso_read_dir_entry_cmd *cmd, int version) { netiso_read_dir_entry_result result_v1; netiso_read_dir_entry_result_v2 result_v2; file_stat_t st; struct dirent *entry; char *path; if (version == 1) { memset(&result_v1, 0, sizeof(result_v1)); } else { memset(&result_v2, 0, sizeof(result_v2)); } if (!client->dir || !client->dirpath) { if (version == 1) { result_v1.file_size = BE64(-1); } else { result_v2.file_size = BE64(-1); } goto send_result; } while ((entry = readdir(client->dir))) { if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0 && strlen(entry->d_name) <= 65535) break; } if (!entry) { closedir(client->dir); free(client->dirpath); client->dir = NULL; client->dirpath = NULL; if (version == 1) { result_v1.file_size = BE64(-1); } else { result_v2.file_size = BE64(-1); } goto send_result; } path = (char *)malloc(strlen(client->dirpath)+strlen(entry->d_name)+2); sprintf(path, "%s/%s", client->dirpath, entry->d_name); if (stat_file(path, &st) < 0) { closedir(client->dir); free(client->dirpath); client->dir = NULL; client->dirpath = NULL; if (version == 1) { result_v1.file_size = BE64(-1); } else { result_v2.file_size = BE64(-1); } DPRINTF("Stat failed on read dir entry: %s\n", path); free(path); goto send_result; } free(path); if ((st.mode & S_IFDIR) == S_IFDIR) { if (version == 1) { result_v1.file_size = BE64(0); result_v1.is_directory = 1; } else { result_v2.file_size = BE64(0); result_v2.is_directory = 1; } } else { if (version == 1) { result_v1.file_size = BE64(st.file_size); result_v1.is_directory = 0; } else { result_v2.file_size = BE64(st.file_size); result_v2.is_directory = 0; } } if (version == 1) { result_v1.fn_len = BE16(strlen(entry->d_name)); } else { result_v2.fn_len = BE16(strlen(entry->d_name)); result_v2.atime = BE64(st.atime); result_v2.ctime = BE64(st.ctime); result_v2.mtime = BE64(st.mtime); } send_result: if (version == 1) { if (send(client->s, (char *)&result_v1, sizeof(result_v1), 0) != sizeof(result_v1)) { DPRINTF("send error on read dir entry (%d)\n", get_network_error()); return -1; } } else { if (send(client->s, (char *)&result_v2, sizeof(result_v2), 0) != sizeof(result_v2)) { DPRINTF("send error on read dir entry (%d)\n", get_network_error()); return -1; } } if ((version == 1 && result_v1.file_size != BE64(-1)) || (version == 2 && result_v2.file_size != BE64(-1))) { if (send(client->s, (char *)entry->d_name, strlen(entry->d_name), 0) != strlen(entry->d_name)) { DPRINTF("send file name error on read dir entry (%d)\n", get_network_error()); return -1; } } return 0; }
static int process_open_cmd(client_t *client, netiso_open_cmd *cmd) { file_stat_t st; netiso_open_result result; char *filepath; uint16_t fp_len; int ret, viso = VISO_NONE; result.file_size = BE64(-1); result.mtime = BE64(0); fp_len = BE16(cmd->fp_len); //DPRINTF("fp_len = %d\n", fp_len); filepath = (char *)malloc(fp_len+1); if(!filepath) { DPRINTF("CRITICAL: memory allocation error\n"); return -1; } if(client->ro_file) { delete client->ro_file; } ret = recv_all(client->s, (void *)filepath, fp_len); filepath[fp_len] = 0; if(!strcmp(filepath, "/CLOSEFILE")) { free(filepath); return 0; } if(ret != fp_len) { DPRINTF("recv failed, getting filename for open: %d %d\n", ret, get_network_error()); free(filepath); return -1; } filepath = translate_path(filepath, 1, &viso); if(!filepath) { DPRINTF("Path cannot be translated. Connection with this client will be aborted.\n"); return -1; } if(viso == VISO_NONE) { client->ro_file = new File(); } else { printf("building virtual iso...\n"); client->ro_file = new VIsoFile((viso == VISO_PS3)); } client->CD_SECTOR_SIZE = 2352; if(client->ro_file->open(filepath, O_RDONLY) < 0) { printf("open error on \"%s\" (viso=%d)\n", filepath + root_len, viso); delete client->ro_file; client->ro_file = NULL; } else { if(client->ro_file->fstat(&st) < 0) { DPRINTF("Error in fstat\n"); } else { result.file_size = BE64(st.file_size); result.mtime = BE64(st.mtime); if(viso != VISO_NONE || BE64(st.file_size) > 0x400000UL) printf("open %s\n", filepath + root_len); // detect cd sector size (2MB - 848MB) if(IS_RANGE(st.file_size, 0x200000UL, 0x35000000UL)) { char buffer[0x10] = ""; client->CD_SECTOR_SIZE = 0; client->ro_file->seek(0x8020UL, SEEK_SET); client->ro_file->read(buffer, 0xC); if(memcmp(buffer, "PLAYSTATION ", 0xC) == 0) client->CD_SECTOR_SIZE = 2048; else { client->ro_file->seek(0x9220UL, SEEK_SET); client->ro_file->read(buffer, 0xC); if(memcmp(buffer, "PLAYSTATION ", 0xC) == 0) client->CD_SECTOR_SIZE = 2336; else { client->ro_file->seek(0x9320UL, SEEK_SET); client->ro_file->read(buffer, 0xC); if(memcmp(buffer, "PLAYSTATION ", 0xC) == 0) client->CD_SECTOR_SIZE = 2352; else { client->ro_file->seek(0x9920UL, SEEK_SET); client->ro_file->read(buffer, 0xC); if(memcmp(buffer, "PLAYSTATION ", 0xC) == 0) client->CD_SECTOR_SIZE = 2448; }}} if(client->CD_SECTOR_SIZE > 0) printf("CD sector size: %i\n", client->CD_SECTOR_SIZE); else client->CD_SECTOR_SIZE = 2352; } } } #ifdef WIN32 DPRINTF("File size: %I64x\n", st.file_size); #else DPRINTF("File size: %llx\n", (long long unsigned int)st.file_size); #endif free(filepath); ret = send(client->s, (char *)&result, sizeof(result), 0); if(ret != sizeof(result)) { DPRINTF("open, send result error: %d %d\n", ret, get_network_error()); return -1; } return 0; }
static int process_stat_cmd(client_t *client, netiso_stat_cmd *cmd) { netiso_stat_result result; file_stat_t st; char *filepath; uint16_t fp_len; int ret; fp_len = BE16(cmd->fp_len); //DPRINTF("fp_len = %d\n", fp_len); filepath = (char *)malloc(fp_len+1); if (!filepath) { DPRINTF("CRITICAL: memory allocation error\n"); return -1; } filepath[fp_len] = 0; ret = recv_all(client->s, (char *)filepath, fp_len); if (ret != fp_len) { DPRINTF("recv failed, getting filename for stat: %d %d\n", ret, get_network_error()); free(filepath); return -1; } filepath = translate_path(filepath, 1, 1, NULL); if (!filepath) { DPRINTF("Path cannot be translated. Connection with this client will be aborted.\n"); return -1; } DPRINTF("stat %s\n", filepath); if (stat_file(filepath, &st) < 0) { DPRINTF("stat error on \"%s\"\n", filepath); result.file_size = BE64(-1); } else { if ((st.mode & S_IFDIR) == S_IFDIR) { result.file_size = BE64(0); result.is_directory = 1; } else { result.file_size = BE64(st.file_size); result.is_directory = 0; } result.mtime = BE64(st.mtime); result.ctime = BE64(st.ctime); result.atime = BE64(st.atime); } free(filepath); ret = send(client->s, (char *)&result, sizeof(result), 0); if (ret != sizeof(result)) { DPRINTF("stat, send result error: %d %d\n", ret, get_network_error()); return -1; } return 0; }
static int process_read_dir_entry_cmd(client_t *client, netiso_read_dir_entry_cmd *cmd, int version) { char *path; file_stat_t st; struct dirent *entry; size_t d_name_len = 0; netiso_read_dir_entry_result result_v1; netiso_read_dir_entry_result_v2 result_v2; if(version == 1) { memset(&result_v1, 0, sizeof(result_v1)); } else { memset(&result_v2, 0, sizeof(result_v2)); } if(!client->dir || !client->dirpath) { if(version == 1) { result_v1.file_size = BE64(-1); } else { result_v2.file_size = BE64(-1); } goto send_result_read_dir; } while ((entry = readdir(client->dir))) { if(IS_PARENT_DIR(entry->d_name)) continue; d_name_len = strlen(entry->d_name); if(IS_RANGE(d_name_len, 1, 65535)) break; } if(!entry) { closedir(client->dir); if(client->dirpath) free(client->dirpath); client->dir = NULL; client->dirpath = NULL; if(version == 1) { result_v1.file_size = BE64(-1); } else { result_v2.file_size = BE64(-1); } goto send_result_read_dir; } path = (char *)malloc(strlen(client->dirpath) + d_name_len + 2); if(!path) { DPRINTF("CRITICAL: memory allocation error\n"); goto send_result_read_dir; } sprintf(path, "%s/%s", client->dirpath, entry->d_name); DPRINTF("Read dir entry: %s\n", path); if(stat_file(path, &st) < 0) { closedir(client->dir); if(client->dirpath) free(client->dirpath); client->dir = NULL; client->dirpath = NULL; if(version == 1) { result_v1.file_size = BE64(-1); } else { result_v2.file_size = BE64(-1); } DPRINTF("Stat failed on read dir entry: %s\n", path); goto send_result_read_dir; } if((st.mode & S_IFDIR) == S_IFDIR) { if(version == 1) { result_v1.file_size = BE64(0); result_v1.is_directory = 1; } else { result_v2.file_size = BE64(0); result_v2.is_directory = 1; } } else { if(version == 1) { result_v1.file_size = BE64(st.file_size); result_v1.is_directory = 0; } else { result_v2.file_size = BE64(st.file_size); result_v2.is_directory = 0; } } if(version == 1) { result_v1.fn_len = BE16(d_name_len); } else { result_v2.fn_len = BE16(d_name_len); result_v2.atime = BE64(st.atime); result_v2.ctime = BE64(st.ctime); result_v2.mtime = BE64(st.mtime); } send_result_read_dir: if(path) free(path); if(version == 1) { if(send(client->s, (char *)&result_v1, sizeof(result_v1), 0) != sizeof(result_v1)) { DPRINTF("send error on read dir entry (%d)\n", get_network_error()); return -1; } } else { if(send(client->s, (char *)&result_v2, sizeof(result_v2), 0) != sizeof(result_v2)) { DPRINTF("send error on read dir entry (%d)\n", get_network_error()); return -1; } } if((version == 1 && result_v1.file_size != BE64(-1)) || (version == 2 && result_v2.file_size != BE64(-1))) { if(send(client->s, (char *)entry->d_name, d_name_len, 0) != d_name_len) { DPRINTF("send file name error on read dir entry (%d)\n", get_network_error()); return -1; } } return 0; }
static int process_open_cmd(client_t *client, netiso_open_cmd *cmd) { file_stat_t st; netiso_open_result result; char *filepath; uint16_t fp_len; int ret, viso; int error = 0; fp_len = BE16(cmd->fp_len); //DPRINTF("fp_len = %d\n", fp_len); filepath = (char *)malloc(fp_len+1); if (!filepath) { DPRINTF("CRITICAL: memory allocation error\n"); return -1; } filepath[fp_len] = 0; ret = recv_all(client->s, (void *)filepath, fp_len); if (ret != fp_len) { DPRINTF("recv failed, getting filename for open: %d %d\n", ret, get_network_error()); free(filepath); return -1; } filepath = translate_path(filepath, 1, 1, &viso); if (!filepath) { DPRINTF("Path cannot be translated. Connection with this client will be aboreted.\n"); return -1; } DPRINTF("open %s\n", filepath); if (client->ro_file) { delete client->ro_file; } if (viso == VISO_NONE) { client->ro_file = new File(); } else { client->ro_file = new VIsoFile((viso == VISO_PS3)); } if (client->ro_file->open(filepath, O_RDONLY) < 0) { DPRINTF("open error on \"%s\" (viso=%d)\n", filepath, viso); error = 1; delete client->ro_file; client->ro_file = NULL; } else { if (client->ro_file->fstat(&st) < 0) { DPRINTF("Error in fstat\n"); error = 1; } else { result.file_size = BE64(st.file_size); result.mtime = BE64(st.mtime); } } #ifdef WIN32 DPRINTF("File size: %I64x\n", st.file_size); #else DPRINTF("File size: %llx\n", (long long unsigned int)st.file_size); #endif if (error) { result.file_size = BE64(-1); result.mtime = BE64(0); } free(filepath); ret = send(client->s, (char *)&result, sizeof(result), 0); if (ret != sizeof(result)) { DPRINTF("open, send result error: %d %d\n", ret, get_network_error()); return -1; } return 0; }
int main(int argc,char *argv[]) { if(argc<2) { printf("Usage: %s [elf path]\n",argv[0]); return 0; } int fd = open(argv[1],OFLAGS); if(fd<0) { fprintf(stderr,"Unable to open elf file: %s\n",argv[1]); return 1; } elf_version(EV_CURRENT); Elf *elf = elf_begin(fd,ELF_C_READ,NULL); if(!elf) { fprintf(stderr,"libelf could not read elf file: %s\n",elf_errmsg(elf_errno())); return 1; } Elf_Scn *prx = getSection(elf,".sys_proc_prx_param"); if(!prx || memcmp(elf_getdata(prx,NULL)->d_buf,prx_magic,sizeof(prx_magic))) { fprintf(stderr,"elf does not have a prx parameter section.\n"); return 1; } Elf_Scn *stubsection = getSection(elf,".lib.stub"); Elf_Data *stubdata = elf_getdata(stubsection,NULL); Elf64_Shdr *stubshdr = elf64_getshdr(stubsection); Stub *stubbase = (Stub*)stubdata->d_buf; size_t stubcount = stubdata->d_size/sizeof(Stub); Elf_Scn *fnidsection = getSection(elf,".rodata.sceFNID"); Elf64_Shdr *fnidshdr = elf64_getshdr(fnidsection); for(Stub *stub = stubbase;stub<stubbase + stubcount;stub++) { uint32_t fnid = BE32(stub->fnid); uint32_t end = fnidshdr->sh_addr + fnidshdr->sh_size; for(Stub *substub = stubbase;substub<(stubbase + stubcount);substub++) { if(stub==substub) continue; uint32_t newfnid = BE32(substub->fnid); if(newfnid>=fnid && newfnid<end) end = newfnid; } uint16_t fnidcount = (end - fnid)/4; if(BE16(stub->imports)!=fnidcount) { lseek(fd,stubshdr->sh_offset + (stub - stubbase)*sizeof(Stub)+offsetof(Stub,imports),SEEK_SET); fnidcount = BE16(fnidcount); if(write(fd,&fnidcount,sizeof(fnidcount))!=sizeof(fnidcount)) { printf("Error occurred during write in %s:%d\n",__FILE__,__LINE__); } } } Elf_Scn *opdsection = getSection(elf,".opd"); Elf_Data *opddata = elf_getdata(opdsection,NULL); Elf64_Shdr *opdshdr = elf64_getshdr(opdsection); Opd64 *opdbase = (Opd64*)opddata->d_buf; size_t opdcount = opddata->d_size/sizeof(Opd64); for(Opd64 *opd = opdbase;opd<(opdbase + opdcount);opd++) { opd->data = BE64(((BE64(opd->func)<<32ULL) | (BE64(opd->rtoc)&0xffffffffULL))); lseek(fd,opdshdr->sh_offset + (opd - opdbase)*sizeof(Opd64),SEEK_SET); if(write(fd,opd,sizeof(Opd64))!=sizeof(Opd64)) { printf("Error occurred during write in %s:%d\n",__FILE__,__LINE__); } } elf_end(elf); close(fd); return 0; }
static int process_read_dir_cmd(client_t *client, netiso_read_dir_entry_cmd *cmd) { (void) cmd; int64_t dir_size = 0; netiso_read_dir_result result; memset(&result, 0, sizeof(result)); netiso_read_dir_result_data *dir_entries = (netiso_read_dir_result_data *) malloc(sizeof(netiso_read_dir_result_data) * MAX_ENTRIES); memset(dir_entries, 0, sizeof(netiso_read_dir_result_data) * MAX_ENTRIES); if(!client->dir || !client->dirpath || !dir_entries) { result.dir_size = (0); goto send_result_read_dir_cmd; } size_t d_name_len, dirpath_len; dirpath_len = strlen(client->dirpath); file_stat_t st; struct dirent *entry; while ((entry = readdir(client->dir))) { if(!entry) break; if(IS_PARENT_DIR(entry->d_name)) continue; d_name_len = strlen(entry->d_name); if(IS_RANGE(d_name_len, 1, MAX_PATH_LEN)) { char *path = (char*)malloc(dirpath_len + d_name_len + 2); if(!path) break; sprintf(path, "%s/%s", client->dirpath, entry->d_name); st.file_size = 0; st.mode = S_IFDIR; st.mtime = 0; st.atime = 0; st.ctime = 0; stat_file(path, &st); if(!st.mtime) st.mtime = st.ctime; if(!st.mtime) st.mtime = st.atime; if((st.mode & S_IFDIR) == S_IFDIR) { dir_entries[dir_size].file_size = (0); dir_entries[dir_size].is_directory = 1; } else { dir_entries[dir_size].file_size = BE64(st.file_size); dir_entries[dir_size].is_directory = 0; } snprintf(dir_entries[dir_size].name, MAX_PATH_LEN, "%s", entry->d_name); dir_entries[dir_size].mtime = BE64(st.mtime); free(path); dir_size++; if(dir_size >= MAX_ENTRIES) break; } } #ifdef WIN32 #ifdef MERGE_DRIVES if(root_len > 2 && dirpath_len > (root_len + 1) && strncmp(client->dirpath, root_directory, root_len) == 0) { memmove(client->dirpath + 2, client->dirpath + root_len, strlen(client->dirpath + root_len) + 1); client->dirpath[1] = ':'; dirpath_len = strlen(client->dirpath); if(client->dir) {closedir(client->dir); client->dir = NULL;} for(int drive = 'C'; drive <= 'Z'; drive++) { if(dir_size >= MAX_ENTRIES) break; if(ignore_drives) { bool ignore = false; for(uint8_t d = 0; d < ignore_drives_len; d++) if((ignore_drives[d] & 0xFF) == drive) {ignore = true; break;} if(ignore) continue; } client->dirpath[0] = drive; if(stat_file(client->dirpath, &st) < 0) continue; client->dir = opendir(client->dirpath); while ((entry = readdir(client->dir))) { if(!entry) break; if(IS_PARENT_DIR(entry->d_name)) continue; d_name_len = entry->d_namlen; //strlen(entry->d_name); if(IS_RANGE(d_name_len, 1, MAX_PATH_LEN)) { char *path = (char*)malloc(dirpath_len + d_name_len + 2); if(path) break; sprintf(path, "%s/%s", client->dirpath, entry->d_name); st.file_size = 0; st.mode = S_IFDIR; st.mtime = 0; st.atime = 0; st.ctime = 0; stat_file(path, &st); if(!st.mtime) st.mtime = st.ctime; if(!st.mtime) st.mtime = st.atime; if((st.mode & S_IFDIR) == S_IFDIR) { dir_entries[dir_size].file_size = (0); dir_entries[dir_size].is_directory = 1; } else { dir_entries[dir_size].file_size = BE64(st.file_size); dir_entries[dir_size].is_directory = 0; } snprintf(dir_entries[dir_size].name, MAX_PATH_LEN, "%s", entry->d_name); dir_entries[dir_size].mtime = BE64(st.mtime); free(path); dir_size++; if(dir_size >= MAX_ENTRIES) break; } } } } #endif #endif if(client->dir) {closedir(client->dir); client->dir = NULL;} send_result_read_dir_cmd: result.dir_size = BE64(dir_size); if(send(client->s, (const char*)&result, sizeof(result), 0) != sizeof(result)) { if(dir_entries) free(dir_entries); return -1; } if(dir_size > 0) { if(send(client->s, (const char*)dir_entries, (sizeof(netiso_read_dir_result_data)*dir_size), 0) != (int)(sizeof(netiso_read_dir_result_data)*dir_size)) { if(dir_entries) free(dir_entries); return -1; } } if(dir_entries) free(dir_entries); return 0; }