// Edit a filetype action void filetypeed_edit_action( filetype_ed_data *data, short action, char *name) { Cfg_Function *function; FunctionStartup *startup; BOOL success=0; // Allocate startup data if (!(startup=AllocVec(sizeof(FunctionStartup),MEMF_CLEAR))) return; // Find the function we want to edit if (!(function=FindFunctionType(&data->type->function_list,action))) { // Allocate a new function function=NewFunction(0,action); } // Otherwise, copy the function else function=CopyFunction(function,0,0); // Valid function? if (function) { // Copy startup data *startup=data->func_startup; startup->window=data->window; startup->function=function; startup->owner_ipc=data->ipc; startup->object=data->type; startup->object_flags=action; // Build title lsprintf(startup->title,"%s : %s",data->type->type.name,name); // Launch editor if ((IPC_Launch( &data->proc_list, &data->editor[action], "dopus_function_editor", (ULONG)IPC_NATIVE(FunctionEditor), STACK_DEFAULT, (ULONG)startup, (struct Library *)DOSBase)) && data->editor[action]) success=1; } // Free data if not successful if (!success) { FreeFunction(function); FreeVec(startup); } }
void FunctionEditor(void) { struct IntuiMessage *gmsg,msg; int break_flag=0; UWORD gadgetid=0; ULONG waitbits; FuncEdData *data; IPCData *ipc; NewConfigWindow newwin; FunctionStartup *startup=0; IPCMessage *submsg; int success=0; BOOL open_window=1; BPTR lock; ConfigWindow windims; // Do startup if (!(ipc=Local_IPC_ProcStartup((ULONG *)&startup, (APTR)&funced_init))) { funced_cleanup(startup->data); return; } // Get data pointer data=startup->data; // Lock RAM: and CD to it if ((lock=Lock("ram:",ACCESS_READ))) lock=CurrentDir(lock); // Copy dimensions if (startup->flags&FUNCEDF_CENTER) windims=_function_editor_window_center; else if (startup->flags&FUNCEDF_LABEL) windims=_function_editor_label_window; else windims=_function_editor_window; // Fill in new window newwin.parent=startup->window; newwin.dims=&windims; newwin.title=(startup->title[0])?startup->title:(char *)GetString(startup->locale,MSG_FUNCED_TITLE); newwin.locale=startup->locale; newwin.port=0; newwin.flags=WINDOW_VISITOR|WINDOW_AUTO_KEYS|WINDOW_REQ_FILL;//|WINDOW_SIZE_BOTTOM; newwin.font=0; // Build flag list funced_build_flaglist(data); waitbits=1<<ipc->command_port->mp_SigBit|1<<data->drag.timer->port->mp_SigBit; // Event loop FOREVER { // Check drag if (config_drag_check(&data->drag)) { // End drag functioned_end_drag(data,0); } // Task message? while ((submsg=(IPCMessage *)GetMsg(ipc->command_port))) { // Close message? if (submsg->command==IPC_QUIT) { // Keep changes? success=submsg->flags; // Set break flag break_flag=1; } // Activate else if (submsg->command==IPC_ACTIVATE && data->window) { WindowToFront(data->window); ActivateWindow(data->window); } // Hide else if (submsg->command==IPC_HIDE && data->window) { // Store changes in function funced_store_edits(data); // End any drag in progress functioned_end_drag(data,0); // Remove AppWindow RemoveAppWindow(data->appwindow); data->appwindow=0; // Close window CloseConfigWindow(data->window); // Zero stuff data->window=0; data->objlist=0; waitbits=1<<ipc->command_port->mp_SigBit; } // Show else if (submsg->command==IPC_SHOW && !data->window) { // Set flag to open window open_window=1; newwin.parent=(struct Window *)submsg->data; } // Passed-along app message else if (submsg->command==CFG_APPMESSAGE_PASS) { funced_appmsg(data,submsg->data); ReplyMsg((struct Message *)submsg->data); } // Update our identity else if (submsg->command==CFG_NEW_ID) { data->function->function.func_type=submsg->flags; startup->object_flags=(ULONG)submsg->data; } // Copy a function else if (submsg->command==FUNCTIONEDIT_COPY_LINE) { FunctionEntry *entry,*next; // Copy function functioned_copy_line( data, (FunctionEntry *)submsg->data, 0, (Point *)submsg->data_free); // Free function entry=(FunctionEntry *)submsg->data; while (entry) { // Get next next=(FunctionEntry *)entry->node; // Free entry FreeVec(entry); entry=next; } } // Clip button else if (submsg->command==BUTTONEDIT_CLIP_BUTTON) { Cfg_ButtonFunction *func; // Show busy pointer SetWindowBusy(data->window); // Stop editing funced_end_edit(data,data->edit_node,0,0); data->edit_node=0; // Get first function if ((func=(Cfg_ButtonFunction *) FindFunctionType( (struct List *)&((Cfg_Button *)submsg->data)->function_list, FTYPE_LEFT_BUTTON))) { FunctionEntry dummy; Cfg_Instruction *ins; // Go through instructions for (ins=(Cfg_Instruction *)func->instructions.mlh_Head; ins->node.mln_Succ; ins=(Cfg_Instruction *)ins->node.mln_Succ) { // Fill out dummy entry dummy.type=ins->type; if (ins->string) strcpy(dummy.buffer,ins->string); else dummy.buffer[0]=0; // Copy function line data->edit_node=funced_new_entry(data,0,&dummy); } // Start editing last line funced_start_edit(data); // Get flags data->function->function.flags=func->function.flags; data->function->function.code=func->function.code; data->function->function.qual=func->function.qual; data->function->function.qual_mask=func->function.qual_mask; data->function->function.qual_same=func->function.qual_same; // Update flag list funced_update_flaglist(data); // Update key funced_show_key(data); } // Free button FreeButton((Cfg_Button *)submsg->data); // Clear busy pointer ClearWindowBusy(data->window); } // Reply the message IPC_Reply(submsg); } // Open window? if (open_window) { // Open window if (!(data->window=OpenConfigWindow(&newwin)) || !(data->p_objlist=AddObjectList( data->window, (startup->flags&FUNCEDF_IMAGE)?_function_editor_image_objects: ((startup->flags&FUNCEDF_LABEL)?_function_editor_label_objects: _function_editor_normal_objects))) || !(data->objlist=AddObjectList(data->window,_function_editor_objects))) break; // Add use or save button AddObjectList(data->window,(startup->flags&FUNCEDF_SAVE)?_function_editor_objects_save:_function_editor_objects_use); // Store window for drag data->drag.window=data->window; // Set window ID SetWindowID(data->window,0,WINDOW_FUNCTION_EDITOR,(struct MsgPort *)ipc); // Add menus AddWindowMenus(data->window,_funced_menus); // Make this an AppWindow data->appwindow=AddAppWindowA(0,0,data->window,data->appport,0); // Get waitbits waitbits|=1<<data->window->UserPort->mp_SigBit; if (data->appwindow) waitbits|=1<<data->appport->mp_SigBit; // Disable key? if (startup->flags&FUNCEDF_NO_KEY) { DisableObject(data->objlist,GAD_FUNCED_KEY,TRUE); } // Initialise gadgets with function data. funced_init_gads(data); open_window=0; } // Intuimessage if (data->window) { while ((gmsg=GetWindowMsg(data->window->UserPort))) { Att_Node *node; // Copy message and reply (unless IDCMPUPDATE) msg=*gmsg; if (gmsg->Class!=IDCMP_IDCMPUPDATE) { ReplyWindowMsg(gmsg); gmsg=0; } // Get GadgetID if (msg.Class==IDCMP_GADGETDOWN || msg.Class==IDCMP_GADGETUP) gadgetid=((struct Gadget *)msg.IAddress)->GadgetID; // Look at message switch (msg.Class) { // Key press case IDCMP_VANILLAKEY: // If editing something, activate string gadget if (data->edit_node) ActivateStrGad(GADGET(GetObject(data->objlist,GAD_FUNCED_EDIT)),data->window); break; // Close window case IDCMP_CLOSEWINDOW: // Set break flag break_flag=1; break; // Mouse move case IDCMP_MOUSEMOVE: // Handle drag move config_drag_move(&data->drag); break; // Inactive window does menu down case IDCMP_INACTIVEWINDOW: msg.Code=MENUDOWN; // Mouse buttons case IDCMP_MOUSEBUTTONS: // Valid drag info? if (data->drag.drag) { short ok=-1; // Dropped ok? if (msg.Code==SELECTUP) { // Is shift down? if (msg.Qualifier&(IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) data->drag_shift=1; else data->drag_shift=0; // Remember last position data->drag.drag_x=data->window->WScreen->MouseX; data->drag.drag_y=data->window->WScreen->MouseY; ok=1; } // Aborted else if (msg.Code==MENUDOWN) { // Set abort ok=0; } // End drag? if (ok!=-1) functioned_end_drag(data,ok); } break; // Menu case IDCMP_MENUPICK: { struct MenuItem *item; // Get item if (!(item=ItemAddress(data->window->MenuStrip,msg.Code))) break; // Treat as gadget gadgetid=MENUID(item); } // Gadget case IDCMP_GADGETUP: case IDCMP_GADGETDOWN: // Look at gadget ID switch (gadgetid) { // Hotkey case GAD_FUNCED_KEY: { IX ix; char *ptr; // Get key, see if it's invalid if ((ptr=(char *)GetGadgetValue(data->objlist,GAD_FUNCED_KEY)) && *ptr) { // Try to parse if (ParseIX(ptr,&ix)) { // Flash screen DisplayBeep(data->window->WScreen); // Activate key field again ActivateStrGad(GADGET(GetObject(data->objlist,GAD_FUNCED_KEY)),data->window); } else { data->function->function.code=ix.ix_Code; data->function->function.qual=QualValid(ix.ix_Qualifier); data->function->function.qual_mask=ix.ix_QualMask; data->function->function.qual_same=ix.ix_QualSame; } } } break; // Flag selected case GAD_FUNCED_FLAGS: // Get selected node node=Att_FindNode(data->flag_list,msg.Code); // Set flag data->function->function.flags^=node->data; // Check change funced_check_flag(&data->function->function.flags,node->data); // Update flag list funced_update_flaglist(data); break; // Edit a line case GAD_FUNCED_LISTER: // Get selected node node=Att_FindNode(data->func_display_list,msg.Code); // Is this the node we're already editing? if (node==data->edit_node) break; // If we're editing another one, store its contents if (data->edit_node) funced_end_edit(data,data->edit_node,0,0); // Start editing this entry data->edit_node=node; funced_start_edit(data); break; // Return pressed in edit line case GAD_FUNCED_EDIT: // See if we were editing something if (data->edit_node) { // Stop editing funced_end_edit(data,data->edit_node,END_DISABLE,msg.Qualifier); data->edit_node=0; } break; // New entry case GAD_FUNCED_NEW_ENTRY: case GAD_FUNCED_INSERT_ENTRY: // Create new entry functioned_copy_line(data,0,gadgetid,0); break; // Delete entry case GAD_FUNCED_DELETE_ENTRY: // Check we were editing something if (!data->edit_node) break; // Stop editing (signal delete) funced_end_edit(data,data->edit_node,END_DISABLE|END_DELETE,0); data->edit_node=0; break; // Function type case GAD_FUNCED_FUNCTION_TYPE: // Check we were editing something if (!data->edit_node) break; // Store type ((FunctionEntry *)data->edit_node->data)->type=msg.Code; // Disable popup button if no functions DisableObject( data->objlist, GAD_FUNCED_EDIT_GLASS, (msg.Code==INST_COMMAND && !data->startup->func_list)); break; // Glass gadget case GAD_FUNCED_EDIT_GLASS: // Check we were editing something if (data->edit_node) { char buffer[256]; // Put up requester if (!(funced_command_req( data, buffer, ((FunctionEntry *)data->edit_node->data)->type))) break; // Insert string in edit line funced_edit_insertstring( data->objlist, GAD_FUNCED_EDIT, buffer, DOpusBase,(struct Library *)IntuitionBase); } break; // Argument list case GAD_FUNCED_EDIT_ARGUMENT: // Check we were editing something if (data->edit_node) { char buffer[80]; // Put up requester if (!(funced_command_req( data, buffer, -1))) break; // Insert string in edit line funced_edit_insertstring( data->objlist, GAD_FUNCED_EDIT, buffer, DOpusBase,(struct Library *)IntuitionBase); } break; // Export case MENU_FUNCED_EXPORT_ASCII: case MENU_FUNCED_EXPORT_CMD: // Got file requester? if (WINREQUESTER(data->window)) { struct TagItem tags[6]; struct FileRequester *req=WINREQUESTER(data->window); // Show busy pointer SetWindowBusy(data->window); // File requester tags tags[0].ti_Tag=ASLFR_Window; tags[0].ti_Data=(ULONG)data->window; tags[1].ti_Tag=ASLFR_TitleText; tags[1].ti_Data=(ULONG)GetString(startup->locale,MSG_FUNCED_SELECT_FILE); tags[2].ti_Tag=ASLFR_Flags1; tags[2].ti_Data=FRF_DOSAVEMODE|FRF_PRIVATEIDCMP; tags[3].ti_Tag=ASLFR_Flags2; tags[3].ti_Data=FRF_REJECTICONS; tags[4].ti_Tag=(gadgetid==MENU_FUNCED_EXPORT_CMD)?ASLFR_InitialDrawer:TAG_DONE; tags[4].ti_Data=(ULONG)"DOpus5:Commands"; tags[5].ti_Tag=TAG_DONE; // Show filerequester if (AslRequest(req,tags)) { // Build filename strcpy(data->buffer,req->fr_Drawer); AddPart(data->buffer,req->fr_File,256); // Store changes in function funced_store_edits(data); // Do export if (gadgetid==MENU_FUNCED_EXPORT_CMD) function_export_cmd(data->buffer,0,data->function); else L_FunctionExportASCII(data->buffer,0,data->function,startup->a4); } // Remove busy pointer ClearWindowBusy(data->window); } break; // Cut/Copy case MENU_FUNCED_CUT: case MENU_FUNCED_COPY: { APTR iff; // Set busy pointer SetWindowBusy(data->window); // Open clipboard if ((iff=IFFOpen((char *)0,IFF_CLIP_WRITE,ID_OPUS))) { // Stop editing funced_end_edit(data,data->edit_node,END_DISABLE,0); data->edit_node=0; // Store changes in function funced_store_edits(data); // Save function SaveFunction(iff,data->function); // Close clipboard IFFClose(iff); } // Just copy, not cut? if (gadgetid==MENU_FUNCED_COPY) { // Clear busy pointer ClearWindowBusy(data->window); break; } // Fall through, paste null function } // Paste case MENU_FUNCED_PASTE: { Cfg_Function *func=0; // Set busy pointer SetWindowBusy(data->window); // End any edit funced_end_edit(data,data->edit_node,END_DISABLE,0); data->edit_node=0; // Paste? if (gadgetid==MENU_FUNCED_PASTE) { APTR iff; // Open clipboard if ((iff=IFFOpen((char *)0,IFF_CLIP_READ,ID_OPUS))) { // Find function if (IFFNextChunk(iff,ID_FUNC)) { // Read function func=ReadFunction(iff,0,0,0); } // Close clipboard IFFClose(iff); } // No valid function? if (!func) { // Flash error DisplayBeep(data->window->WScreen); ClearWindowBusy(data->window); break; } } // Detach existing list SetGadgetChoices(data->objlist,GAD_FUNCED_FLAGS,(APTR)~0); // Clear function list Att_RemList(data->function_list,REMLIST_SAVELIST|REMLIST_FREEDATA); // Free existing instructions FreeInstructionList(data->function); // Rebuild display list funced_build_display(data); // Clear flags data->function->function.flags=0; funced_update_flaglist(data); // Clear key data->function->function.code=0xffff; SetGadgetValue(data->objlist,GAD_FUNCED_KEY,0); // Clear label if (startup->flags&FUNCEDF_LABEL) { data->label[0]=0; SetGadgetValue(data->p_objlist,GAD_FUNCED_LABEL,0); } // Paste function in? if (func) { short type; // Save type type=data->function->function.func_type; // Copy function in CopyFunction(func,0,data->function); data->function->function.func_type=type; // Free copied function FreeFunction(func); // Initialise gadgets funced_init_gads(data); } // Clear busy pointer ClearWindowBusy(data->window); } break; // Use case GAD_FUNCED_USE: success=1; // Cancel case GAD_FUNCED_CANCEL: break_flag=1; break; } break; // Key press case IDCMP_RAWKEY: // Help? if (msg.Code==0x5f && !(msg.Qualifier&VALID_QUALIFIERS)) { // Set busy pointer SetWindowBusy(data->window); // Send help command IPC_Command(startup->main_owner,IPC_HELP,(1<<31),"Function Editor",0,REPLY_NO_PORT); // Clear busy pointer ClearWindowBusy(data->window); } break; // BOOPSI message case IDCMP_IDCMPUPDATE: { struct TagItem *tags=(struct TagItem *)msg.IAddress; short item; // Check ID if (GetTagData(GA_ID,0,tags)!=GAD_FUNCED_LISTER) break; // Get item if ((item=GetTagData(DLV_DragNotify,-1,tags))!=-1) { // Start the drag config_drag_start(&data->drag,data->func_display_list,item,tags,TRUE); } } break; // Ticks case IDCMP_INTUITICKS: ++data->drag.tick_count; break; } // Reply to any outstanding message if (gmsg) ReplyWindowMsg(gmsg); } } // AppMessage if (data->appwindow) { struct AppMessage *msg; while ((msg=(struct AppMessage *)GetMsg(data->appport))) { // Make sure window is active ActivateWindow(data->window); // Handle message funced_appmsg(data,msg); ReplyMsg((struct Message *)msg); } } // Check break flag if (break_flag) break; // Wait for message Wait(waitbits); } // Restore CD if (lock) UnLock(CurrentDir(lock)); // Edit successful? if (success) { FunctionReturn ret; // Store changes in function funced_store_edits(data); // Fill out return data ret.object=startup->object; ret.object_flags=startup->object_flags; ret.function=data->function; // Send new function back IPC_Command(startup->owner_ipc,FUNCTIONEDIT_RETURN,0,&ret,0,REPLY_NO_PORT); } // End any drag in progress functioned_end_drag(data,0); // Free edit function FreeFunction(data->function); // Close window RemoveAppWindow(data->appwindow); CloseConfigWindow(data->window); // Close application port if (data->appport) { struct Message *msg; while ((msg=GetMsg(data->appport))) ReplyMsg(msg); DeleteMsgPort(data->appport); } // Say goodbye IPC_Goodbye(ipc,startup->owner_ipc,startup->object_flags); // Delete IPC data Forbid(); IPC_Free(ipc); // Free data funced_cleanup(data); FreeVec(startup); }
// Receive edit from function editor short filetypeed_receive_edit( filetype_ed_data *data, FunctionReturn *ret) { Cfg_Function *function=0; Cfg_Function *func_copy=0; BOOL no_func=0,icon=0; func_node *fndata=0; short success=0; // Is the new function empty? if (IsListEmpty((struct List *)&ret->function->instructions)) no_func=1; // Try to copy the new function if (no_func || (func_copy=CopyFunction(ret->function,0,0))) { // Icon menu? (this is a bit kludgy) if (ret->object_flags>15) { Att_Node *node; // Go through icon list for (node=(Att_Node *)data->icon_list->list.lh_Head; node->node.ln_Succ; node=(Att_Node *)node->node.ln_Succ) { // Match function if (((func_node *)node->data)->func==(Cfg_Function *)ret->object_flags) { // Get function pointer function=(Cfg_Function *)ret->object_flags; break; } } icon=1; } // Otherwise, find the function we want to replace else function=FindFunctionType(&data->type->function_list,ret->object_flags); // Add new function to the list if (func_copy) { // Fix type if (!icon) func_copy->function.func_type=ret->object_flags; // Add to list, in same position if applicable if (function) Insert(&data->type->function_list,&func_copy->node,&function->node); else AddTail(&data->type->function_list,&func_copy->node); } // Free old function if (function) { // Remove function and free it Remove(&function->node); FreeFunction(function); } // Store for icon menu if (fndata) fndata->func=func_copy; success=(icon)?2:1; } return success; }
// Most of the work is done in main()... int main( int argc, char* argv[] ) { // Print out help message if needed. if (argc != 2) { printf("*** Code Crypt 0.0 by [email protected] ***\n"); printf("*** ***\n"); printf("*** Usage: codecrypt filename.exe ***\n"); printf("*** Will encrypt the codesection to avoid detection ***\n"); printf("*** Disclaimer: This software is for educational ***\n"); printf("*** purposes only. No responsibility is held or ***\n"); printf("*** accepted for misuse. ***\n"); return 0; } // The file to pack is the 1st argument. LPCSTR fileName = argv[1]; // Open the .exe file to be packed. HANDLE hFile = CreateFileA( fileName, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); // Did the file open work? if (hFile == INVALID_HANDLE_VALUE) { DWORD x = GetLastError(); // No, get out. printf("Cannot open file '%s'...exiting!\n", argv[1]); char *buf; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,x,0, (LPTSTR) &buf,0,NULL); printf("Error: %d, Error Code:%d\n", buf, x); return 1; } // Get size of file. This is needed because we need to tell the // CreateFileMapping function to add memory to the end of the // memory-mapped file. We will later use this memory to add in the // unpacker stub and its required data. LARGE_INTEGER bigInt; BOOL r = GetFileSizeEx(hFile, &bigInt); if (!r) { printf("Cannot get file size.\n"); return 1; } // Is the file too big to add in the unpacker stub? DWORD fileSize = bigInt.LowPart; if (fileSize + 0x2000 >= ULONG_MAX) { printf("The file is too big to pack.\n"); return 1; } // Create a handle to a memory mapped file. Note that this does not // actually map the file, it just creates the handle that will actually be // mapped later. Note that extra space is allocated at the end to // the mapped file for the unpacker stub. HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, bigInt.HighPart, bigInt.LowPart + 0x2000 , NULL); // Did creating the file mapping handle work? if (hFileMap == NULL) { printf("Unable to create file mapping! Exiting..."); return 1; } // Map the .exe file into memory. The map is set up so we can read and // write to it. LPVOID hMap = MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); // Did mapping the file to memory work? if (hMap == NULL) { printf("Unable to map file into memory! Exiting..."); return 1; } // Get the DOS header from the .exe file. This is the 1st thing in the // file. PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hMap; // This packer only works with .exe files. Make sure we have one. // The e_magic field tells us what sort of file this is. if (!(pDosHeader->e_magic == IMAGE_DOS_SIGNATURE)) { printf("This packer only works with .exe files.\n"); return 1; } // Get the IMAGE_NT_HEADER. This has 3 fields, the signature (which should // be set 0x00004550 for valid PE files), the file header, and the // optional file header. PIMAGE_NT_HEADERS pNTHeader; // The e_lfanew field in the DOS header gives us the offset to the // IMAGE_NT_HEADER. pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDosHeader, pDosHeader->e_lfanew); // Check to make sure this is a PE file we are working with. if (!(pNTHeader->Signature == IMAGE_NT_SIGNATURE)) { printf("This packer only works with PE files.\n"); printf("Signature for PE files is %x. Current signature is %x\n", IMAGE_NT_SIGNATURE, pNTHeader->Signature); return 1; } // The entire .exe image is stored in a HMODULE structure. Cast the memory // mapped file so it can be viewed as an HMODULE. HMODULE *hModule = (HMODULE *) hMap; // Grab a pointer to the IMAGE_OPTIONAL_HEADER structure, which contains // information about the size of the code and all data sections, where to // find the sections, etc. // // The IMAGE_OPTIONAL_HEADER structure is contained in the IMAGE_NT_HEADER // in the OptionalHeader field. // // Note that we are assuming that we are working with a 32bit executable. PIMAGE_OPTIONAL_HEADER32 optionHeader = (PIMAGE_OPTIONAL_HEADER32) &(pNTHeader->OptionalHeader); // Get the RVA (relative virtual address) of the first byte of code when // loaded into memory. To find the actual address of the code add the load // address (in this case the address of hModule) to the RVA. VOID* baseCodeRVA = (VOID*)optionHeader->BaseOfCode; // Get the combined size of all code sections. DWORD codeSize = optionHeader->SizeOfCode; // TCC does not seem to set the SizeOfCode field, so executables // compiled with TCC cannot be packed with this packer. if (codeSize < 1) { printf("SizeOfCode field is < 1. Cannot pack.\n"); printf("The execuatble may have been compiled with TCC.\n"); return 1; } // After the MAGE_NT_HEADERS is the section table. The section table is an // array of IMAGE_SECTION_HEADERs structures. An IMAGE_SECTION_HEADER // provides information about its associated section. // // Use the IMAGE_FIRST_SECTION macro defined in winnt.h to get the address // of the 1st IMAGE_SECTION_HEADER. // DQ (4/23/2017): I don't see that this macro will work with WINE (modified to support testing). // IMAGE_SECTION_HEADER* firstSectionHeader = // IMAGE_FIRST_SECTION32(pNTHeader); IMAGE_SECTION_HEADER* firstSectionHeader = NULL; // Get a pointer to the code block. The code block is found by adding the // base load address to the code RVA. PVOID codePtr = MakePtr(void *, hModule, baseCodeRVA); // Unprotect the code so we can encrypt it in place. DWORD oldProt = 0; BOOL diditwork = VirtualProtect(codePtr, codeSize, PAGE_READWRITE, &oldProt); // Did the code unprotection work? if (!diditwork) { DWORD x = GetLastError(); printf("Cannot unprotect code (error code %d).\n", x); return 0; } // Find the section containing the code. We have already // calculated the code relative virtual base address // (baseCodeRVA), so now we need to find the section whose base // RVA is the same as the RVA of the code. IMAGE_SECTION_HEADER* codeSection = FindSection(firstSectionHeader, pNTHeader->FileHeader.NumberOfSections, (DWORD) baseCodeRVA); // Can we find the section with the code? if (codeSection == NULL) { printf("Cannot find code section.\n"); return 0; } // Get the raw memory address (inside HMODULE) and size of the code. DWORD rawCodePosition = codeSection->PointerToRawData; DWORD virtualCodeSize = codeSection->Misc.VirtualSize; // Compute the actual, in-memory start and end address of the code // block. DWORD startpos = (DWORD)hModule + (DWORD)rawCodePosition; DWORD endpos = startpos + virtualCodeSize; // Encrypt the code by incrementing each byte in the code by 1. printf("Starting to encrypt code section...\n"); DWORD currAddr; for (currAddr = startpos; currAddr < endpos; currAddr++) { (*((char *) currAddr))++; } printf("Done encrypting code section.\n"); // Get the last section. We will be tacking the unpacking code // onto the end of the last section (if we have room). IMAGE_SECTION_HEADER* lastSection = FindLastSection(firstSectionHeader, pNTHeader->FileHeader.NumberOfSections); char sectName[10]; int i; for (i = 0; i < 8; i++) { sectName[i] = lastSection->Name[i]; } sectName[8] = '\0'; printf("Adding stub to section: name = %s, Raw size = %d, Raw Data ptr = %d\n", sectName, lastSection->SizeOfRawData, lastSection->PointerToRawData); // We will be adding the unpacker stub to the last section in the // PE file. In that section, we will be adding the unpacker stub // code right after the existing data in the section. DWORD* storageSpot = (DWORD*)((DWORD)hModule + (DWORD)lastSection->PointerToRawData + (DWORD)lastSection->SizeOfRawData); // Get the unpacking code and store it in a contiguous chunk of memory. char *decryptRoutine = CopyFunction(&DecryptAndStart); DWORD decryptSize = GetFunctionSize(&DecryptAndStart); if (decryptSize > 0x2000) { printf("Decryption routine too large.\n"); return 1; } printf("Size of stub = %d\n", decryptSize); // Now start putting data into memory as it will be laid out in // the packed executable. // Track the # of pieces of initialization data added. int numInitData = 0; // Store the RVA of the packed code furthest away from the stub. *(storageSpot + numInitData++) = (DWORD)baseCodeRVA; // Store original code entry RVA at storagespot next closest to // the stub. *(storageSpot + numInitData++) = (DWORD)optionHeader->AddressOfEntryPoint; // Store the image base (used with the code base RVA to figure out // where the code to unpack is in memory in the unpacker stub) at // the next closest spot. *(storageSpot + numInitData++) = (DWORD)optionHeader->ImageBase; // Store size of code (in bytes) to unpack at the spot closest to // the stub. *(storageSpot + numInitData++) = virtualCodeSize; // Add our decryption routine to storageSpot + (# of data DWORDS // added). The +(# of data DWORDS written) is there so that the // unpacker stub data added above is not overwritten by the stub. // // Note that storageSpot is a pointer to a DWORD, so adding 1 to // storageSpot advances by 1 DWORD, not 1 BYTE. memcpy(storageSpot + numInitData, decryptRoutine, decryptSize); // Now update the header for the last section (i.e. one with // highest RVA) and extend this by size needed and set it to // executable. // Add the size of the unpacker stub and its initialization data // to all of the size tracking fields in the IMAGE_OPTIONAL_HEADER. optionHeader->SizeOfImage += 0x2000; optionHeader->SizeOfCode += 0x2000; optionHeader->SizeOfInitializedData += 0x2000; // Set the new initial entry point to the unpacker stub. optionHeader->AddressOfEntryPoint = // Start in last section... (DWORD)lastSection->VirtualAddress + // At the end of its original data... (DWORD)lastSection->SizeOfRawData + // Past the unpacker stub initialization data (4 DWORDs). (sizeof(DWORD))*numInitData; // Add the size of the unpacker stub and its initialization data // to all of the size tracking fields the last section header. lastSection->Misc.VirtualSize += 0x2000; lastSection->SizeOfRawData += 0x2000; lastSection->Characteristics = IMAGE_SCN_MEM_WRITE| IMAGE_SCN_MEM_READ| IMAGE_SCN_MEM_EXECUTE| IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_CNT_INITIALIZED_DATA| IMAGE_SCN_CNT_CODE;//0xE00000E0; // Finally we need to set the main code section as writable for // our stub to decrypt it. We will do this by making ALL sections // writable. MakeAllSectionsWritable(firstSectionHeader, pNTHeader->FileHeader.NumberOfSections); // Close the packed file. CloseHandle(hFile); }
// Do a filetype on a function (? :-) void function_filetype(FunctionHandle *handle) { Cfg_Filetype *type,*last_type=0; Cfg_Function *func,*type_function=0,*old_function; struct List filechange_list; struct Node *node,*next=0; unsigned short qual; // Extract qualifier qual=(handle->data>>16)&0xffff; handle->data&=0xffff; // Backup function pointer old_function=handle->function; // Lock filetype list lock_listlock(&GUI->filetypes,FALSE); // Steal the filechange list NewList(&filechange_list); for (node=handle->filechange.lh_Head;node->ln_Succ;node=next) { next=node->ln_Succ; Remove(node); AddTail(&filechange_list,node); } // Got arguments? if (handle->args) { struct ArgArrayEntry *arg; // Go through list for (arg=(struct ArgArrayEntry *)handle->args->aa_List.mlh_Head; arg->ae_Node.mln_Succ; arg=(struct ArgArrayEntry *)arg->ae_Node.mln_Succ) { // Match filetype for this file if (!(type=filetype_identify(arg->ae_String,handle->data,0,qual))) { // Couldn't match. Was this a drag & drop operation? if (handle->flags&FUNCF_DRAG_DROP) { // Use "default" filetype (copy) type=default_filetype; } } // Got filetype? if (type) { // Get appropriate function if ((func=FindFunctionType(&type->function_list,handle->data))) { ExternalEntry *entry; // Different to the last type? if (last_type && type!=last_type) { // Anything in the external list? if (!(IsListEmpty((struct List *)&handle->external_list)) && type_function) { Cfg_Function *copy; // Initialise handle function function_handle_init(handle,1); // Copy the function if ((copy=CopyFunction(type_function,handle->memory,0))) { // Set function pointer handle->function=copy; // Unlock the filetype list unlock_listlock(&GUI->filetypes); // Run function function_run_function(handle); // Free the function FreeFunction(copy); // Lock filetype list again lock_listlock(&GUI->filetypes,FALSE); // Steal new filechanges for (node=handle->filechange.lh_Head;node->ln_Succ;node=next) { next=node->ln_Succ; Remove(node); AddTail(&filechange_list,node); } } // Clear external list NewList((struct List *)&handle->external_list); } } // Save type pointer last_type=type; // Save function pointer type_function=func; // Create a new external entry if ((entry=new_external_entry(handle,arg->ae_String))) { // Add to external entry list AddTail((struct List *)&handle->external_list,(struct Node *)entry); } } } } } // Anything left in the external list? if (!(IsListEmpty((struct List *)&handle->external_list)) && type_function) { Cfg_Function *copy; // Initialise handle function function_handle_init(handle,1); // Copy the function if ((copy=CopyFunction(type_function,handle->memory,0))) { // Set function pointer handle->function=copy; // Unlock the filetype list unlock_listlock(&GUI->filetypes); // Run function function_run_function(handle); // Free the function FreeFunction(copy); // Lock filetype list again lock_listlock(&GUI->filetypes,FALSE); // Steal new filechanges for (node=handle->filechange.lh_Head;node->ln_Succ;node=next) { next=node->ln_Succ; Remove(node); AddTail(&filechange_list,node); } } } // Unlock the filetype list unlock_listlock(&GUI->filetypes); // Restore function pointer handle->function=old_function; // Copy filechange list back for (node=filechange_list.lh_Head;node->ln_Succ;node=next) { next=node->ln_Succ; Remove(node); AddTail(&handle->filechange,node); } }