Exemple #1
0
        static void Main(string[] args)
        {
            Console.WriteLine(">> Loading configuration options...");
            if (!Config.Load(args))
                return;

            if (Config.NoCmsg && Config.NoSmsg)
            {
                Logger.WriteConsoleLine("Please give me something to do.");
                Config.ShowHelp();
                return;
            }

            Logger.CreateOutputStream(Config.OutputFile);

            Console.WriteLine(">> Opening Wow client...");
            ClientStream = new BinaryReader(File.OpenRead(Config.Executable));
            if (!BaseStream.CanRead)
                return;

            ClientBytes = File.ReadAllBytes(Config.Executable);
            Disasm = new UnmanagedBuffer(ClientBytes);
            Env = Emulator.Create(BaseStream);

            if (!Config.NoSmsg)
            {
                Console.WriteLine(">> Discovering JAM groups...");
                foreach (var pattern in ClientGroupPatterns) // Load jam groups...
                {
                    var offsets = ClientBytes.FindPattern(pattern, 0xFF);
                    if (offsets.Count == 0)
                    {
                        Console.WriteLine(@"Could not find group name "" {0}""", System.Text.Encoding.ASCII.GetString(pattern.Skip(1).ToArray()));
                        return;
                    }
                    else
                    {
                        Console.WriteLine(@"Found JAM Group "" {0}""", System.Text.Encoding.ASCII.GetString(pattern.Skip(1).ToArray()));
                        Dispatchers.Add(new JamDispatch((int)(offsets[0] + 1)));
                    }
                }
            }

            if (!Config.NoGhNames && !Opcodes.TryPopulate())
                return;

            if (!Config.NoSmsg)
                SMSG.Dump();

            if (!Config.NoCmsg)
                CMSG.Dump(Config.SpecificOpcodeValue);
        }
Exemple #2
0
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine(">> Loading configuration options...");
                if (!Config.Load(args))
                {
                    return;
                }

                if (Config.NoCmsg && Config.NoSmsg)
                {
                    Logger.WriteConsoleLine("Please give me something to do.");
                    Config.ShowHelp();
                    return;
                }

                if ((Config.BinDiff == string.Empty) != (Config.Opcode == string.Empty))
                {
                    Console.WriteLine("ERROR: -d and -o flags need to be both present to function!");
                    return;
                }

                if (Config.BinDiff != string.Empty && Config.Opcode != string.Empty)
                {
                    Console.WriteLine(">> Opening Diff...");
                    FuncDiff = new BinDiff(Config.BinDiff);
                    if (!FuncDiff.openConnection())
                    {
                        Console.WriteLine(">> Failed to open diff!");
                        return;
                    }

                    Console.WriteLine(">> Opening OpcodeTable...");
                    OpTable = new OpcodeTable(Config.Opcode);
                    if (!OpTable.openConnection())
                    {
                        Console.WriteLine(">> Failed to open OpcodeTable!");
                        return;
                    }
                }

                if (Logger.CreateOutputStream(Config.OutputFile))
                {
                    Logger.PrepOutputStram();
                }

                Console.WriteLine(">> Opening Wow client...");
                ClientStream = new BinaryReader(File.OpenRead(Config.Executable));
                if (!BaseStream.CanRead)
                {
                    return;
                }

                ClientBytes = File.ReadAllBytes(Config.Executable);
                Disasm      = new UnmanagedBuffer(ClientBytes);
                Environment = Emulator.Create(BaseStream);

                ClientBuild = new Dumpers.Build();
                Logger.WriteLine("Detected build {0}.{1}", ClientBuild.Version, ClientBuild.BuildNumber);
                switch (ClientBuild.isBuildSupported())
                {
                case Dumpers.BuildSupport.BUILD_UNKOWN:
                    Console.WriteLine("\nBuild not yet implemented!\nThere might be unexpected results running opcodedumper.");
                    break;

                case Dumpers.BuildSupport.BUILD_UNSUPPORTED:
                    Console.WriteLine("\nBuild unsupported!\nNameOffset has changed since this build. You can try using an old version.");
                    return;

                case Dumpers.BuildSupport.BUILD_SUPPORTED:
                    Console.WriteLine("Build Supported!");
                    break;
                }

                Console.WriteLine(">> Discovering JAM groups...");
                foreach (var pattern in ClientGroupPatterns) // Load jam groups...
                {
                    var offsets = ClientBytes.FindPattern(pattern, 0xFF);
                    if (offsets.Count == 0)
                    {
                        Console.WriteLine(@"Could not find group name "" {0}""", System.Text.Encoding.ASCII.GetString(pattern.Skip(1).ToArray()));
                        return;
                    }
                    else
                    {
                        Console.WriteLine(@"Found JAM Group "" {0}""", System.Text.Encoding.ASCII.GetString(pattern.Skip(1).ToArray()));
                        var dispatch = new JamDispatch((int)(offsets[0] + 1));
                        Dispatchers[dispatch.GetGroup()] = dispatch;
                    }
                }

                if (!Config.NoGhNames && !Opcodes.TryPopulate())
                {
                    return;
                }

                if (!Config.NoSmsg)
                {
                    Dumpers.SMSG.Dump();
                }

                if (!Config.NoCmsg)
                {
                    Dumpers.CMSG.Dump(Config.SpecificOpcodeValue);
                }

                if (Config.WPP)
                {
                    Dumpers.CMSG.dumpWPPFile("Opcodes.cs");
                }
            }
            catch (SystemException e)
            {
                Console.WriteLine("Caught level exception: \n{0}\n\nDid you use the correct command line arguments? Use -help to show usage.\nPress any key to exit...", e.Message);
                Console.ReadKey();
            }
        }
        private bool ExecuteASM(Disasm disasm, UnmanagedBuffer buffer, bool followCalls)
        {
            if (Interrupted)
                return false;

            var entryPoint = buffer.Ptr.ToInt32();
            var disassemblyString = disasm.CompleteInstr;
            // Sanitize the instruction.
            if (disassemblyString.IndexOf(";") != -1)
                disassemblyString = disassemblyString.Remove(disassemblyString.IndexOf(";"));

            disassemblyString = Regex.Replace(disassemblyString, @"\s+", " ", RegexOptions.IgnoreCase).Trim();

            if (Regex.IsMatch(disassemblyString, @"[!@#$%^&()={}\\|/?<>.~`""'_]"))
                return false;

            if (disassemblyString.Length == 0 || disassemblyString.EndsWith(":"))
                return false;

            var tokens = disassemblyString.Split(' ');
            var mnemonic = tokens[0];

            //Console.WriteLine("0x{0:X8} {1}", disasm.EIP.ToInt64(), disasm.CompleteInstr);

            if (disassemblyString.Contains("call far") || disassemblyString.Contains("xmm"))
                return false;

            List<InstructionArgument> arguments = new List<InstructionArgument>();
            // TODO Support for floating point opcodes

            var parametersList = disassemblyString.Replace(mnemonic, String.Empty).Trim().Split(new char[]{ ',' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var parameter in parametersList)
                arguments.Add(new InstructionArgument(this, parameter.Trim()));
            if (mnemonic[0] == 'j')
            {
                if (ExecuteJump(disassemblyString, disasm, mnemonic))
                {
                    var jumpOffset = arguments[0].GetValue();
                    if (arguments[0].Type == ArgumentType.Memory)
                        jumpOffset += (uint)entryPoint - 0x400C00;
                    disasm.EIP = new IntPtr(jumpOffset);
                    return true;
                } else return false;
            }
            else
            {
                InstructionArgument src = null;
                InstructionArgument dst = null;
                InstructionArgument extra = null;

                if (parametersList.Length == 1)
                    dst = src = arguments[0];
                else if (parametersList.Length == 2)
                {
                    dst = arguments[0];
                    src = arguments[1];
                }
                else if (parametersList.Length == 3)
                    extra = arguments[2];

                switch (mnemonic)
                {
                    case "ret": case "retn":
                        // Actually use the stack here.
                        if (JumpBacks.Count > 0)
                        {
                            Pop(4);
                            disasm.EIP = new IntPtr(JumpBacks[0]);
                            JumpBacks.RemoveAt(0);
                            return true;
                        }
                        return false;
                    case "leave":
                        break;
                    case "nop": break;
                    #region Data transfer
                    case "mov":
                        if (parametersList.Length != 2 || dst.Type == ArgumentType.Immediate)
                            break;
                        if (src.Type == ArgumentType.Immediate && src.Size > dst.Size)
                            break;
                        if (src.Type != ArgumentType.Immediate && src.Size != dst.Size)
                            break;
                        dst.SetValue(src.GetValue());
                        break;
                    case "movzx":
                    {
                        if (parametersList.Length != 2 || dst.Type != ArgumentType.Register ||
                            src.Type == ArgumentType.Immediate || src.Size >= dst.Size)
                            break;
                        //! TODO Unhack this - Handles indirect jumptables
                        //! TODO: Really need to fix memory - this superbly fails now
                        //if (dst.Register == null)
                        //{
                            /*if (src.Size == 4)
                                addr = buffer.ReadDword(src.Address - 0x400C00);
                            else if (src.Size == 2)
                                addr = (uint)buffer.ReadWord(src.Address - 0x400C00);
                            else if (src.Size == 1)
                                addr = (uint)buffer.ReadByte(src.Address - 0x400C00);*/
                        //}
                        dst.SetValue(src.GetValue());
                        break;
                    }
                    case "movsb":
                        WriteByteToMemory(Edi.Value, ReadByteFromMemory(Esi.Value));
                        Ecx.Value--;
                        if (EFlags.HasFlag(EFlags.DirectionFlag))
                        {
                            Edi.Value--;
                            Esi.Value--;
                        }
                        else
                        {
                            Edi.Value++;
                            Esi.Value++;
                        }
                        break;
                    case "movsw":
                        WriteWordToMemory(Edi.Value, ReadWordFromMemory(Esi.Value));
                        Ecx.Value--;
                        if (EFlags.HasFlag(EFlags.DirectionFlag))
                        {
                            Edi.Value -= 2;
                            Esi.Value -= 2;
                        }
                        else
                        {
                            Edi.Value += 2;
                            Esi.Value += 2;
                        }
                        break;
                    case "movsd":
                        WriteDwordToMemory(Edi.Value, ReadDwordFromMemory(Esi.Value));
                        Ecx.Value--;
                        if (EFlags.HasFlag(EFlags.DirectionFlag))
                        {
                            Edi.Value -= 4;
                            Esi.Value -= 4;
                        }
                        else
                        {
                            Edi.Value += 4;
                            Esi.Value += 4;
                        }
                        break;
                    case "stosb":
                        WriteByteToMemory(Edi.Value, Eax.Al);
                        Ecx.Value--;
                        if (EFlags.HasFlag(EFlags.DirectionFlag))
                        {
                            Edi.Value--;
                            Esi.Value--;
                        }
                        else
                        {
                            Edi.Value++;
                            Esi.Value++;
                        }
                        break;
                    case "stosw":
                        WriteWordToMemory(Edi.Value, Eax.Ax);
                        Ecx.Value--;
                        if (EFlags.HasFlag(EFlags.DirectionFlag))
                        {
                            Edi.Value -= 2;
                            Esi.Value -= 2;
                        }
                        else
                        {
                            Edi.Value += 2;
                            Esi.Value += 2;
                        }
                        break;
                    case "stosd":
                        WriteDwordToMemory(Edi.Value, Eax.Value);
                        Ecx.Value--;
                        if (EFlags.HasFlag(EFlags.DirectionFlag))
                        {
                            Edi.Value -= 4;
                            Esi.Value -= 4;
                        }
                        else
                        {
                            Edi.Value += 4;
                            Esi.Value += 4;
                        }
                        break;
                    case "xchg":
                        if (parametersList.Length != 2 || dst.Type != ArgumentType.Register
                            || src.Type == ArgumentType.Immediate || src.Size != dst.Size)
                            break;

                        uint tmp = src.GetValue();
                        src.SetValue(dst.GetValue());
                        dst.SetValue(tmp);
                        break;
                    case "lea":
                        if (parametersList.Length == 2 && dst.Type == ArgumentType.Register && src.Type == ArgumentType.Memory && src.Size > 1)
                            dst.SetValue(src.Address);
                        break;
                    #endregion
                    #region Basic maths
                    case "inc":
                        if (parametersList.Length == 1 && dst.Type != ArgumentType.Immediate)
                        {
                            ulong val = (ulong)dst.GetValue() + 1;
                            UpdateFlags(val, dst.Size, EFlags.OverflowFlag | EFlags.SignFlag | EFlags.ZeroFlag | EFlags.AdjustFlag | EFlags.ParityFlag);
                            dst.SetValue((uint)val);
                        }
                        break;
                    case "dec":
                        if (parametersList.Length == 1 && dst.Type != ArgumentType.Immediate)
                        {
                            ulong val = (ulong)dst.GetValue() - 1;
                            UpdateFlags(val, dst.Size, EFlags.OverflowFlag | EFlags.SignFlag | EFlags.ZeroFlag | EFlags.AdjustFlag | EFlags.ParityFlag);
                            dst.SetValue((uint)val);
                        }
                        break;
                    case "not":
                        if (parametersList.Length == 1 && dst.Type != ArgumentType.Immediate)
                            dst.SetValue(~dst.GetValue());
                        break;
                    case "neg":
                        if (parametersList.Length == 1 && dst.Type != ArgumentType.Immediate)
                        {
                            ulong val = (ulong)(-(long)dst.GetValue());
                            UpdateFlags(val, dst.Size, EFlags.OverflowFlag | EFlags.SignFlag | EFlags.ZeroFlag | EFlags.AdjustFlag | EFlags.ParityFlag | EFlags.CarryFlag);
                            dst.SetValue((uint)val);
                        }
                        break;
                    case "bswap":
                        if (parametersList.Length != 1 || dst.Type != ArgumentType.Register || dst.Size != 4)
                            break;
                        uint dval = dst.GetValue();
                        dst.SetValue((uint)((dval << 24) | ((dval & 0xFF00) << 8) | ((dval & 0xFF0000) >> 8) | (dval >> 24)));
                        break;
                    case "add":
                        if (parametersList.Length == 2)
                        {
                            ulong val = (ulong)dst.GetValue() + src.GetValue();
                            UpdateFlags(val, dst.Size, EFlags.OverflowFlag | EFlags.SignFlag | EFlags.ZeroFlag | EFlags.AdjustFlag | EFlags.ParityFlag | EFlags.CarryFlag);
                            dst.SetValue((uint)val);
                        }
                        break;
                    case "sub":
                        if (parametersList.Length == 2)
                        {
                            ulong val = (ulong)dst.GetValue() - (ulong)src.GetValue();
                            UpdateFlags(val, dst.Size, EFlags.OverflowFlag | EFlags.SignFlag | EFlags.ZeroFlag | EFlags.AdjustFlag | EFlags.ParityFlag | EFlags.CarryFlag);
                            dst.SetValue((uint)val);
                        }
                        break;
                    case "mul": // unsigned multiply
                        // The OF and CF flags are set to 0 if the upper half of the result is 0, otherwise they are set to 1
                        if (parametersList.Length != 1 || src.Type == ArgumentType.Immediate)
                            break;
                        switch (src.Size)
                        {
                            case 1:
                                ushort r16 = (ushort)(Eax.Al * src.GetValue());
                                Eax.Ax = r16;
                                ToggleFlagIf(EFlags.OverflowFlag | EFlags.CarryFlag, (r16 >> 8) == 0);
                                break;
                            case 2:
                                uint r32 = Eax.Ax * src.GetValue();
                                Edx.Dx = (ushort)(r32 >> 16);    // high order
                                Eax.Ax = (ushort)(r32 & 0xFFFF); // low order
                                ToggleFlagIf(EFlags.OverflowFlag | EFlags.CarryFlag, Edx.Dx == 0);
                                break;
                            case 4:
                                ulong r64 = Eax.Ax * src.GetValue();
                                Edx.Value = (uint)(r64 >> 32);    // high order
                                Eax.Value = (uint)(r64 & 0xFFFFFFFF); // low order
                                ToggleFlagIf(EFlags.OverflowFlag | EFlags.CarryFlag, Edx.Value == 0);
                                break;
                        }
                        break;
                    case "div":
                        if (src.Type == ArgumentType.Immediate)
                            break;
                        ulong dividend, quotient;
                        uint divisor = src.GetValue();
                        if (divisor == 0)
                            break;

                        if (src.Size == 1)
                        {
                            dividend = Eax.Ax;
                            quotient = dividend / divisor;
                            if (quotient > 0xFF)
                                break;
                            Eax.Al = (byte)quotient;
                            Eax.Ah = (byte)(dividend % divisor);
                        }
                        else if (src.Size == 2)
                        {
                            dividend = ((uint)Edx.Dx << 16) & Eax.Ax;
                            quotient = dividend / divisor;
                            if (quotient > 0xFFFF)
                                break;
                            Eax.Ax = (ushort)quotient;
                            Edx.Dx = (ushort)(dividend % divisor);
                        }
                        else if (src.Size == 4)
                        {
                            dividend = ((ulong)Edx.Value << 32) & Eax.Value;
                            quotient = dividend / divisor;
                            if (quotient > 0xFFFFFFFF)
                                break;
                            Eax.Value = (uint)quotient;
                            Edx.Value = (uint)(dividend % divisor);
                        }
                        break;
                    case "imul": // Signed multiply
                    case "idiv": // Signed division
                        break; // NYI
                    #endregion
                    #region Bitwise operators
                    case "and":
                        if (parametersList.Length == 2)
                        {
                            uint result = dst.GetValue() & src.GetValue();
                            dst.SetValue(result);
                            ClearFlags(EFlags.OverflowFlag | EFlags.CarryFlag);
                            UpdateFlags(result, dst.Size, EFlags.SignFlag | EFlags.ZeroFlag | EFlags.ParityFlag);
                        }
                        break;
                    case "or":
                        if (parametersList.Length == 2)
                        {
                            uint result = dst.GetValue() | src.GetValue();
                            dst.SetValue(result);
                            ClearFlags(EFlags.OverflowFlag | EFlags.CarryFlag);
                            UpdateFlags(result, dst.Size, EFlags.SignFlag | EFlags.ZeroFlag | EFlags.ParityFlag);
                        }
                        else throw new ArgumentException();

                        break;
                    case "xor":
                        if (parametersList.Length == 2)
                        {
                            uint result = dst.GetValue() ^ src.GetValue();
                            dst.SetValue(result);
                            ClearFlags(EFlags.OverflowFlag | EFlags.CarryFlag);
                            UpdateFlags(result, dst.Size, EFlags.SignFlag | EFlags.ZeroFlag | EFlags.ParityFlag);
                        }
                        break;
                    case "stc": // set carry flag
                        SetFlags(EFlags.CarryFlag);
                        break;
                    case "std": // set direction flag
                        SetFlags(EFlags.DirectionFlag);
                        break;
                    case "clc": // clear carry flag
                        ClearFlags(EFlags.CarryFlag);
                        break;
                    case "cld": // clear direction flag
                        ClearFlags(EFlags.DirectionFlag);
                        break;
                    case "shr": // shift right
                    {
                        if (parametersList.Length != 2 || dst.Type == ArgumentType.Immediate
                            || src.Type == ArgumentType.Memory || (src.Type == ArgumentType.Register && src.RegisterName != "cl"))
                            break;
                        uint result = dst.GetValue() >> (byte)src.GetValue();
                        dst.SetValue(result);

                        if (src.Type == ArgumentType.Immediate && src.GetValue() == 1)
                            UpdateFlags(result, dst.Size, EFlags.OverflowFlag | EFlags.SignFlag | EFlags.ZeroFlag  | EFlags.ParityFlag | EFlags.CarryFlag);
                        else
                            UpdateFlags(result, dst.Size, EFlags.SignFlag | EFlags.ZeroFlag | EFlags.ParityFlag | EFlags.CarryFlag);
                        break;
                    }
                    case "shl": // shift left
                    case "sal": // shift arithmetic left (signed)
                    {
                        if (parametersList.Length != 2 || dst.Type == ArgumentType.Immediate || src.Type == ArgumentType.Memory || (src.Type == ArgumentType.Register && src.RegisterName != "cl"))
                            break;

                        ulong result = (ulong)dst.GetValue() << (byte)src.GetValue();
                        dst.SetValue((uint)result);

                        if (src.Type == ArgumentType.Immediate && src.GetValue() == 1)
                            UpdateFlags(result, dst.Size, EFlags.OverflowFlag | EFlags.SignFlag | EFlags.ZeroFlag | EFlags.ParityFlag | EFlags.CarryFlag);
                        else
                            UpdateFlags(result, dst.Size, EFlags.SignFlag | EFlags.ZeroFlag | EFlags.ParityFlag | EFlags.CarryFlag);
                        break;
                    }
                    case "sar": // shift arithmetic right (signed)
                    {
                        if (parametersList.Length != 2 || dst.Type == ArgumentType.Immediate || src.Type == ArgumentType.Memory || (src.Type == ArgumentType.Register && src.RegisterName != "cl"))
                            break;
                        uint result = (uint)((int)dst.GetValue() >> (byte)src.GetValue());
                        dst.SetValue(result);

                        if (src.Type == ArgumentType.Immediate && src.GetValue() == 1)
                            UpdateFlags(result, dst.Size, EFlags.OverflowFlag | EFlags.SignFlag | EFlags.ZeroFlag | EFlags.ParityFlag | EFlags.CarryFlag);
                        else
                            UpdateFlags(result, dst.Size, EFlags.SignFlag | EFlags.ZeroFlag | EFlags.ParityFlag | EFlags.CarryFlag);
                        break;
                    }
                    case "ror": // rotate right
                    {
                        // bits >> n | (bits << (32 - n));
                        uint data = dst.GetValue();
                        uint bitsToShift = src.GetValue();
                        data = data >> (int)bitsToShift | (data << (32 - (int)bitsToShift));
                        dst.SetValue(data);

                        if (src.Type == ArgumentType.Immediate && src.GetValue() == 1)
                            UpdateFlags(data, dst.Size, EFlags.OverflowFlag | EFlags.CarryFlag);
                        else
                            UpdateFlags(data, dst.Size, EFlags.CarryFlag);
                        break;
                    }
                    case "rol": // rotate left
                    {
                        // bits << n | (bits >> (32 - n));
                        uint data2 = dst.GetValue();
                        uint bitsToShift2 = src.GetValue();
                        uint data = data2 << (int)bitsToShift2 | (data2 >> (32 - (int)bitsToShift2));
                        dst.SetValue(data);

                        if (src.Type == ArgumentType.Immediate && src.GetValue() == 1)
                            UpdateFlags(data, dst.Size, EFlags.OverflowFlag | EFlags.CarryFlag);
                        else
                            UpdateFlags(data, dst.Size, EFlags.CarryFlag);
                        break;
                    }
                    #endregion
                    case "call":
                        // TODO Use the stack to keep s and r (saved registers (0) and jumpback offset (+4))
                        // TODO Half done. (see below)
                        var offset = (int)disasm.Instruction.AddrValue - buffer.Ptr.ToInt32();
                        CallOffsets.Add((uint)offset);
                        if (followCalls)
                        {
                            Push(offset+5); // Push the return address on the stack
                            JumpBacks.Add((uint)(disasm.EIP.ToInt32() + 5));
                            disasm.EIP = new IntPtr((int)disasm.Instruction.AddrValue);
                            return true;
                        }
                        return false;
                    case "cmp":
                        UpdateFlags((ulong)dst.GetValue() - (ulong)src.GetValue(), dst.Size, EFlags.OverflowFlag | EFlags.SignFlag | EFlags.ZeroFlag | EFlags.AdjustFlag | EFlags.ParityFlag | EFlags.CarryFlag);
                        break;
                    case "test":
                        ClearFlags(EFlags.OverflowFlag | EFlags.CarryFlag);
                        UpdateFlags(dst.GetValue() & src.GetValue(), dst.Size, EFlags.SignFlag | EFlags.ZeroFlag | EFlags.ParityFlag);
                        break;
                    case "sbb":
                        if (parametersList.Length != 2)
                            break;
                        ulong newValue = (ulong)dst.GetValue() - (ulong)src.GetValue();
                        if (EFlags.HasFlag(EFlags.CarryFlag))
                            newValue -= 1;
                        dst.SetValue((uint)newValue);
                        UpdateFlags(newValue, dst.Size, EFlags.OverflowFlag | EFlags.SignFlag | EFlags.ZeroFlag | EFlags.AdjustFlag | EFlags.CarryFlag);
                        break;
                    #region Stack operations
                    case "push":
                        // todo: check for stack overflow (stack pointer < base address)
                        if (parametersList.Length == 1)
                        {
                            uint s = dst.Size;
                            if (s == 2 || s == 4)
                            {
                                WriteMemory(Esp - s, dst.GetValue());
                                Esp.Value -= s;
                            }
                        }
                        break;
                    case "pop":
                        // todo: check for stack overflow (stack pointer > base address + memory size)
                        if (parametersList.Length == 1 && dst.Type != ArgumentType.Immediate)
                        {
                            uint s = dst.Size;
                            if (s == 2 || s == 4)
                            {
                                dst.SetValue(ReadMemory(Esp, s));
                                Esp.Value += s;
                            }
                        }
                        break;
                    case "pusha":
                        if (parametersList.Length == 0)
                        {
                            WriteMemory(Esp - 2, Eax.Ax);
                            WriteMemory(Esp - 4, Ecx.Cx);
                            WriteMemory(Esp - 6, Edx.Dx);
                            WriteMemory(Esp - 8, Ebx.Bx);
                            WriteMemory(Esp - 10, Esp.Sp);
                            WriteMemory(Esp - 12, Ebp.Bp);
                            WriteMemory(Esp - 14, Esi.Si);
                            WriteMemory(Esp - 16, Edi.Di);
                            Esp.Value -= 16;
                        }
                        break;
                    case "pushad":
                        if (parametersList.Length == 0)
                        {
                            WriteMemory(Esp - 4, Eax.Value);
                            WriteMemory(Esp - 8, Ecx.Value);
                            WriteMemory(Esp - 12, Edx.Value);
                            WriteMemory(Esp - 16, Ebx.Value);
                            WriteMemory(Esp - 20, Esp.Value);
                            WriteMemory(Esp - 24, Ebp.Value);
                            WriteMemory(Esp - 28, Esi.Value);
                            WriteMemory(Esp - 32, Edi.Value);
                            Esp.Value -= 32;
                        }
                        break;
                    case "popa":
                        if (parametersList.Length == 0)
                        {
                            Edi.Di = ReadWordFromMemory(Esp);
                            Esi.Si = ReadWordFromMemory(Esp + 2);
                            Ebp.Bp = ReadWordFromMemory(Esp + 4);
                            //Esp.Sp = ReadWord(Esp + 6);    // ignored
                            Ebx.Bx = ReadWordFromMemory(Esp + 8);
                            Edx.Dx = ReadWordFromMemory(Esp + 10);
                            Ecx.Cx = ReadWordFromMemory(Esp + 12);
                            Eax.Ax = ReadWordFromMemory(Esp + 14);
                            Esp.Value += 16;
                        }
                        else throw new ArgumentException();
                        break;
                    case "popad":
                        if (parametersList.Length == 0)
                        {
                            Edi.Value = ReadDwordFromMemory(Esp);
                            Esi.Value = ReadDwordFromMemory(Esp + 4);
                            Ebp.Value = ReadDwordFromMemory(Esp + 8);
                            //Esp.Value = ReadDoubleword(Esp + 12);    // ignored
                            Ebx.Value = ReadDwordFromMemory(Esp + 16);
                            Edx.Value = ReadDwordFromMemory(Esp + 20);
                            Ecx.Value = ReadDwordFromMemory(Esp + 24);
                            Eax.Value = ReadDwordFromMemory(Esp + 28);
                            Esp.Value += 32;
                        }
                        break;
                        // todo: pushf and popf, and effects on eflags
                    #endregion
                }
            }
            return false;
        }
        public void Execute(uint offset, UnmanagedBuffer buffer, bool followCalls = false)
        {
            try
            {
                Esp.Value -= 4; // Assume we are calling from the beginning of a function. return address is on the stack

                Disasm disasm = new Disasm();
                disasm.EIP = new IntPtr(buffer.Ptr.ToInt64() + offset); // new IntPtr(buffer.Ptr.ToInt64()/* + offset*/);
                while (true)
                {
                    var result = BeaEngine.Disassemble(disasm);
                    if (result == BeaConstants.SpecialInfo.UNKNOWN_OPCODE)
                        return;

                    // Returns true if jumped or following calls
                    var jumped = ExecuteASM(disasm, buffer, followCalls);
                    if ((disasm.CompleteInstr.Contains("leave") || disasm.CompleteInstr.Contains("ret")) && !jumped)
                        break;

                    Debugger.TryTrigger(this, BreakpointType.InstructionName, disasm.Instruction.Mnemonic);

                    if (!jumped)
                        disasm.EIP = new IntPtr(disasm.EIP.ToInt64() + (int)result);
                }
                for (var i = 0; i < CallOffsets.Count; ++i)
                    CallOffsets[i] += 0x400C00;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }
 public void Execute(int offset, UnmanagedBuffer buffer, bool followCalls = false)
 {
     Execute((uint)offset, buffer, followCalls);
 }
Exemple #6
0
        static void Main(string[] args)
        {
            Console.WriteLine(">> Loading configuration options...");
            if (!Config.Load(args))
            {
                return;
            }

            if (Config.NoCmsg && Config.NoSmsg)
            {
                Logger.WriteConsoleLine("Please give me something to do.");
                Config.ShowHelp();
                return;
            }

            Logger.CreateOutputStream(Config.OutputFile);

            Console.WriteLine(">> Opening Wow client...");
            ClientStream = new BinaryReader(File.OpenRead(Config.Executable));
            if (!BaseStream.CanRead)
            {
                return;
            }

            ClientBytes = File.ReadAllBytes(Config.Executable);
            Disasm      = new UnmanagedBuffer(ClientBytes);
            Env         = Emulator.Create(BaseStream);

            if (!Config.NoSmsg)
            {
                Console.WriteLine(">> Discovering JAM groups...");
                foreach (var pattern in ClientGroupPatterns) // Load jam groups...
                {
                    var offsets = ClientBytes.FindPattern(pattern, 0xFF);
                    if (offsets.Count == 0)
                    {
                        Console.WriteLine(@"Could not find group name "" {0}""", System.Text.Encoding.ASCII.GetString(pattern.Skip(1).ToArray()));
                        return;
                    }
                    else
                    {
                        Console.WriteLine(@"Found JAM Group "" {0}""", System.Text.Encoding.ASCII.GetString(pattern.Skip(1).ToArray()));
                        Dispatchers.Add(new JamDispatch((int)(offsets[0] + 1)));
                    }
                }
            }

            if (!Config.NoGhNames && !Opcodes.TryPopulate())
            {
                return;
            }

            if (!Config.NoSmsg)
            {
                SMSG.Dump();
            }

            if (!Config.NoCmsg)
            {
                CMSG.Dump(Config.SpecificOpcodeValue);
            }
        }