Skip to content

Instantly share code, notes, and snippets.

@LordJZ
Created March 17, 2014 20:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LordJZ/9607042 to your computer and use it in GitHub Desktop.
Save LordJZ/9607042 to your computer and use it in GitHub Desktop.
simple guid packet unpacker
#include "stdafx.h"
#include <ida.hpp>
#include <idp.hpp>
#include <loader.hpp>
#include <allins.hpp>
#include <name.hpp>
int __stdcall IDAP_init(void)
{
// "metapc" represents x86 architecture
if (strncmp(inf.procName, "metapc", 8) != 0)
{
error("Only PE and ELF binary type compiled for the x86 platform is supported, sorry.");
return PLUGIN_SKIP;
}
return PLUGIN_OK;
}
void __stdcall IDAP_term(void)
{
// Stuff to do when exiting, generally you'd put any sort
// of clean-up jobs here.
return;
}
void decodeClientJam(ea_t addr)
{
ea_t func = cmd.Op1.addr;
ea_t func_start = func;
int insn_size;
int i = 0;
while ((insn_size = decode_insn(func)) != 0)
{
func += insn_size;
if (cmd.itype == NN_mov && cmd.Op1.type == 3 && cmd.Op1.reg == 0 && cmd.Op1.phrase == 0
&& cmd.Op2.type == 5 && cmd.Op2.value)
{
ea_t ctor_addr;
if (!get_many_bytes(cmd.Op2.value, &ctor_addr, 4))
continue;
int size;
int j = 0;
while ((size = decode_insn(ctor_addr)) != 0)
{
ctor_addr += size;
if (cmd.itype == NN_push && cmd.Op1.type == o_imm)
{
msg("Opcode = %u\n", cmd.Op1.value);
char name[MAXSTR];
if (!get_name(BADADDR, func_start, name, sizeof(name)-1))
{
msg("Cannot get name of %a\n", func_start);
return;
}
if (name[0] == 's' && name[1] == 'u' && name[2] == 'b')
{
char name2[MAXSTR];
sprintf(name2, "UserRouterClient_Constructor::%s_%u", name, cmd.Op1.value);
if (!set_name(func_start, name2))
msg("Cannot set name of %a\n", func_start);
}
else
msg("Not renaming %a because of improper name", func_start);
return;
}
if (++j >= 20)
{
msg("Cannot find push imm in %a :(\n", ctor_addr);
return;
}
}
}
if (++i >= 20)
{
msg("Cannot find vtable in %a :(\n", addr);
return;
}
}
}
void decodePackedData(ea_t addr)
{
int insn_size;
ea_t regbase = 65536;
uint16 reg = 0;
qvector<int> mask;
mask.reserve(16);
qvector<int> bytes;
bytes.reserve(16);
while ((insn_size = decode_insn(addr)) != 0)
{
if (cmd.itype == NN_int3)
{
insn_size = 0;
break;
}
else if (cmd.itype == NN_cmp)
{
op_t src = cmd.Op1;
op_t op = cmd.Op2;
if (op.type == o_imm && op.value == 0 && src.type == o_displ)
{
reg = src.phrase;
regbase = min(src.addr, regbase);
mask.push_back(src.addr);
}
}
else if (cmd.itype == NN_mov)
{
op_t& op = cmd.Op2;
if (op.type == o_displ && op.phrase == reg)
bytes.push_back(op.addr);
}
//msg("Insn at %a (size=%d) is %d\n", addr, insn_size, cmd.itype);
addr += insn_size;
}
msg("mask=%d, bytes=%d\n", mask.size(), bytes.size());
msg("protected override int[] MaskSequence { get { return new int[] { ");
for (int32 i = 0; i < int32(mask.size()); i += 8)
{
for (int32 j = i + 8 - 1; j >= i; --j)
msg("%d, ", mask[j] - regbase);
}
msg("}; } }\n");
msg("protected override int[] ByteSequence { get { return new int[] { ");
for (int32 i = 0; i < int32(bytes.size()); ++i)
msg("%d, ", bytes[i] - regbase);
msg("}; } }\n");
}
// The plugin can be passed an integer argument from the plugins.cfg
// file. This can be useful when you want the one plug-in to do
// something different depending on the hot-key pressed or menu
// item selected.
void __stdcall IDAP_run(int arg)
{
msg("Hello world!\n");
ea_t addr = get_screen_ea();
if (!decode_insn(addr))
{
msg("Unknown insn!\n");
return;
}
if (cmd.itype == NN_call)
decodeClientJam(addr);
else
decodePackedData(addr);
}
// There isn't much use for these yet, but I set them anyway.
char IDAP_comment[] = "Unpacks data (lol)";
char IDAP_help[] = "Buzzle Data Unpacker";
// The name of the plug-in displayed in the Edit->Plugins menu. It can
// be overridden in the user's plugins.cfg file.
char IDAP_name[] = "Buzzle Data Unpacker";
// The hot-key the user can use to run your plug-in.
char IDAP_hotkey[] = "Ctrl+J";
// The all-important exported PLUGIN object
plugin_t PLUGIN =
{
IDP_INTERFACE_VERSION, // IDA version plug-in is written for
PLUGIN_UNL, // Flags (see below)
IDAP_init, // Initialisation function
IDAP_term, // Clean-up function
IDAP_run, // Main plug-in body
IDAP_comment, // Comment – unused
IDAP_help, // As above – unused
IDAP_name, // Plug-in name shown in
// Edit->Plugins menu
IDAP_hotkey // Hot key to run the plug-in
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment