Skip to content

Commit

Permalink
example dont commit: example use of unshield_open2
Browse files Browse the repository at this point in the history
  • Loading branch information
bwrsandman committed Feb 10, 2021
1 parent 4258401 commit d79b4cd
Show file tree
Hide file tree
Showing 2 changed files with 365 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ if(WIN32)
target_link_libraries(unshield-deobfuscate ${ZLIB_LIBRARIES})
endif()

find_package(PkgConfig REQUIRED)
pkg_check_modules(cdio REQUIRED IMPORTED_TARGET libcdio)
pkg_check_modules(iso9660 REQUIRED IMPORTED_TARGET libiso9660)

add_executable(isocab isocab.c)
target_link_libraries(isocab PRIVATE PkgConfig::cdio PkgConfig::iso9660 libunshield)

if(BUILD_STATIC AND MSVC)
set_msvc_runtime_static()
endif()
Expand Down
358 changes: 358 additions & 0 deletions src/isocab.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,358 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <libunshield.h>
#include <cdio/cdio.h>
#include <cdio/iso9660.h>
#include <dirent.h>

bool readfile_cd(const CdIo_t* cd, lsn_t lsn, uint32_t size, uint8_t* buf)
{
uint32_t whole_blocks = size / ISO_BLOCKSIZE;
uint8_t extra_block[ISO_BLOCKSIZE];
bool has_extra_block = size % ISO_BLOCKSIZE != 0;
if (cdio_read_data_sectors(cd, buf, lsn, ISO_BLOCKSIZE, whole_blocks) != DRIVER_OP_SUCCESS) {
return false;
}
if (has_extra_block)
{
if (cdio_read_data_sectors(cd, extra_block, lsn, ISO_BLOCKSIZE, 1) != DRIVER_OP_SUCCESS) {
return false;
}
memcpy(&buf[whole_blocks * ISO_BLOCKSIZE], extra_block, size % ISO_BLOCKSIZE);
}

return true;
}

#if 0
bool readfile_iso(const iso9660_t* iso, lsn_t lsn, uint32_t size, uint8_t* buf)
{
// std::vector <uint8_t> buf;
// uint32_t blocks = size / ISO_BLOCKSIZE + (size % ISO_BLOCKSIZE != 0);
// buf.resize(ISO_BLOCKSIZE * blocks);
// auto read = cd.seek_read(buf.data(), lsn, blocks);
// if (read != ISO_BLOCKSIZE * blocks)
// {
// return {};
// }
// buf.resize(size);
// return buf;
}
#endif


typedef struct {
CdIo_t* cd;
const uint8_t* buf;
uint32_t size;
} IsoCabIoCallbacksCDUserData_t;

typedef enum {
ISO_CAB_FILE_MODE_BINARY = 1 << 0,
ISO_CAB_FILE_MODE_READ = 1 << 1,
ISO_CAB_FILE_MODE_WRITE = 1 << 2,
ISO_CAB_FILE_MODE_AMEND = 1 << 2,
} IsoCabFileMode;

typedef struct {
iso9660_stat_t *stat;
IsoCabFileMode mode;
long int current_offset;
} IsoCabFile;

void* isocab_fopen(const char* filename, const char* modes, void* userdata)
{
IsoCabIoCallbacksCDUserData_t* userdata_cd = (IsoCabIoCallbacksCDUserData_t*)userdata;
printf("%s has been called\n", __FUNCTION__);
iso9660_stat_t *stat = iso9660_fs_stat(userdata_cd->cd, filename);
if (stat == NULL)
{
return NULL;
}
IsoCabFileMode mode = 0;
if (strchr(modes, 'b') != NULL)
{
mode |= ISO_CAB_FILE_MODE_BINARY;
}
if (strchr(modes, 'r') != NULL)
{
mode |= ISO_CAB_FILE_MODE_READ;
}
if (strchr(modes, 'w') != NULL)
{
mode |= ISO_CAB_FILE_MODE_WRITE;
}
if (strchr(modes, 'a') != NULL)
{
mode |= ISO_CAB_FILE_MODE_AMEND;
}
IsoCabFile* file = (IsoCabFile*)malloc(sizeof(IsoCabFile));
file->stat = stat;
file->mode = mode;
file->current_offset = 0;
return file;
}

int isocab_fseek(void* file, long int offset, int whence, void* userdata)
{
IsoCabIoCallbacksCDUserData_t* userdata_cd = (IsoCabIoCallbacksCDUserData_t*)userdata;
IsoCabFile* cab_file = file;
printf("%s has been called\n", __FUNCTION__);
switch (whence)
{
case SEEK_SET:
cab_file->current_offset = offset;
break;
case SEEK_CUR:
cab_file->current_offset += offset;
break;
case SEEK_END:
cab_file->current_offset = cab_file->stat->size - offset;
break;
default:
return -1;
}
return 0;
}

long int isocab_ftell(void* file, void* userdata)
{
IsoCabIoCallbacksCDUserData_t* userdata_cd = (IsoCabIoCallbacksCDUserData_t*)userdata;
IsoCabFile* cab_file = file;
printf("%s has been called\n", __FUNCTION__);
return cab_file->current_offset;
}

size_t isocab_fread(void* ptr, size_t size, size_t n, void* file, void* userdata)
{
IsoCabIoCallbacksCDUserData_t* userdata_cd = (IsoCabIoCallbacksCDUserData_t*)userdata;
IsoCabFile* cab_file = file;
printf("%s has been called\n", __FUNCTION__);
size_t read = 0;
if (readfile_cd(userdata_cd->cd, cab_file->stat->lsn, n * size, ptr))
{
read += size * n;
cab_file->current_offset += size * n;
}
return read;
}

size_t isocab_fwrite(const void* ptr, size_t size, size_t n, void* file, void* userdata)
{
IsoCabIoCallbacksCDUserData_t* userdata_cd = (IsoCabIoCallbacksCDUserData_t*)userdata;
printf("%s has been called\n", __FUNCTION__);
return 0;
}

int isocab_fclose(void* file, void* userdata)
{
IsoCabIoCallbacksCDUserData_t* userdata_cd = (IsoCabIoCallbacksCDUserData_t*)userdata;
IsoCabFile* cab_file = file;
printf("%s has been called\n", __FUNCTION__);
iso9660_stat_free(cab_file->stat);
free(cab_file);
return 0;
}

typedef struct {
char filename[PATH_MAX];
CdioList_t* list;
CdioListNode_t* current_node;
struct dirent current_dirent;
} IsoCabDir;

void* isocab_opendir(const char *name, void* userdata)
{
IsoCabIoCallbacksCDUserData_t* userdata_cd = (IsoCabIoCallbacksCDUserData_t*)userdata;
printf("%s has been called\n", __FUNCTION__);
// TODO don't fix here
if (strlen(name) == 0)
{
name = "/";
}
CdioList_t* list = iso9660_fs_readdir(userdata_cd->cd, name);
if (list == NULL)
{
return NULL;
}
IsoCabDir* dir = (IsoCabDir*)malloc(sizeof(IsoCabDir));
strncpy(dir->filename, name, sizeof(dir->filename));
dir->list = list;
dir->current_node = _cdio_list_begin(dir->list);
return dir;
}

int isocab_closedir(void *dir, void* userdata)
{
IsoCabIoCallbacksCDUserData_t* userdata_cd = (IsoCabIoCallbacksCDUserData_t*)userdata;
IsoCabDir* cab_dir = (IsoCabDir*)dir;
printf("%s has been called\n", __FUNCTION__);
_cdio_list_free(cab_dir->list, true, NULL);
free(cab_dir);
return 0;
}

struct dirent* isocab_readdir(void *dir, void *userdata)
{
IsoCabIoCallbacksCDUserData_t* userdata_cd = (IsoCabIoCallbacksCDUserData_t*)userdata;
IsoCabDir* cab_dir = (IsoCabDir*)dir;
printf("%s has been called\n", __FUNCTION__);
if (cab_dir->current_node == NULL)
{
return NULL;
}
memset(&cab_dir->current_dirent, 0, sizeof(cab_dir->current_dirent));
const iso9660_stat_t* stat = _cdio_list_node_data(cab_dir->current_node);
cab_dir->current_dirent.d_ino = stat->lsn;
cab_dir->current_dirent.d_off = stat->lsn;
cab_dir->current_dirent.d_reclen = stat->size;
switch (stat->type)
{
case _STAT_FILE:
cab_dir->current_dirent.d_type = DT_REG;
break;
case _STAT_DIR:
cab_dir->current_dirent.d_type = DT_DIR;
break;
default:
cab_dir->current_dirent.d_type = DT_UNKNOWN;
break;
}
char filename[PATH_MAX];
iso9660_name_translate(stat->filename, filename);
strncpy(cab_dir->current_dirent.d_name, filename, sizeof(cab_dir->current_dirent.d_name));

cab_dir->current_node = _cdio_list_node_next (cab_dir->current_node);

return &cab_dir->current_dirent;
}

static UnshieldIoCallbacks isocabIoCDCallbacks = {
.fopen = isocab_fopen,
.fseek = isocab_fseek,
.ftell = isocab_ftell,
.fread = isocab_fread,
.fwrite = isocab_fwrite,
.fclose = isocab_fclose,
.opendir = isocab_opendir,
.closedir = isocab_closedir,
.readdir = isocab_readdir,
};

int unshield_buffer_cd(CdIo_t* cd, const char* filename, const uint8_t* buf, uint32_t size)
{
IsoCabIoCallbacksCDUserData_t userdata = {
.cd = cd,
.buf = buf,
.size = size,
};
Unshield* unshield = unshield_open2(filename, &isocabIoCDCallbacks, &userdata);
if (!unshield)
{
fprintf(stderr, "Failed to open %s as an InstallShield Cabinet File\n", filename);
return EXIT_FAILURE;
}

printf("%s contents:\n", filename);
for (int i = 0; i < unshield_component_count(unshield); i++)
{
printf("%s\n", unshield_component_name(unshield, i));
}

return EXIT_SUCCESS;
}

int cdinfo_cd(CdIo_t* cd, const char* cab_filename)
{
iso9660_pvd_t pvd;
if (iso9660_fs_read_pvd(cd, &pvd))
{
printf("Application: %s\n", pvd.application_id);
printf("Preparer: %s\n", pvd.preparer_id);
printf("Publisher: %s\n", pvd.publisher_id);
printf("System: %s\n", pvd.system_id);
printf("Volume: %s\n", pvd.volume_id);
printf("Volume Set: %s\n", pvd.volume_set_id);
}

CdioList_t* list = iso9660_fs_readdir(cd, "/");

if (list)
{
/* Iterate over the list of files. */
CdioListNode_t* node;
_CDIO_LIST_FOREACH(node, list)
{
char filename[4096];
iso9660_stat_t *stat = _cdio_list_node_data(node);
iso9660_name_translate(stat->filename, filename);
printf("%s [LSN %6d] %8u %s%s\n",
2 == stat->type ? "d" : "-",
stat->lsn, stat->size, "/", filename);
}
_cdio_list_free(list, true, NULL);
}

{
iso9660_stat_t *stat = iso9660_fs_stat(cd, cab_filename);
if (stat == NULL)
{
fprintf(stderr, "Could not find %stat\n", cab_filename);
return EXIT_FAILURE;
}
uint8_t* file_buf = malloc(stat->size);
if (!readfile_cd(cd, stat->lsn, stat->size, file_buf))
{
free(file_buf);
return EXIT_FAILURE;
}
printf("%s (%u bytes)\n", cab_filename, stat->size);
int result = unshield_buffer_cd(cd, cab_filename, file_buf, stat->size);
free(file_buf);
if (result != EXIT_SUCCESS)
{
return result;
}
}

return EXIT_SUCCESS;
}

int main(int argc, char *argv[])
{
if (argc < 2)
{
fprintf(stderr, "Missing path to CD-ROM device or pseudo CD-ROM\n");
return EXIT_FAILURE;
}

if (argc < 3)
{
fprintf(stderr, "Missing path to cab file in CD-ROM device or pseudo CD-ROM\n");
return EXIT_FAILURE;
}

{
CdIo_t* device = cdio_open(argv[1], DRIVER_UNKNOWN);
if (device != NULL)
{
printf("CDIO detected the driver: %s\n", cdio_get_driver_name(device));
return cdinfo_cd(device, argv[2]);
}
}

{
iso9660_t* iso = iso9660_open_ext(argv[1], ISO_EXTENSION_NONE);
if (iso != NULL)
{
printf("ISO 9660 detected the driver\n");
return EXIT_SUCCESS;
//return cdinfo(iso);
}
}

fprintf(stderr, "Could not open CD-ROM device or pseudo CD-ROM\n");
return EXIT_FAILURE;
}

0 comments on commit d79b4cd

Please sign in to comment.