Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Topics - RawCode

#21
Help / Mono x86-32 JIT machine code hooks
December 24, 2015, 05:38:45 AM

unsafe static public int HookMethodFromTo
(
Type source_type, string source_method_name,
Type destination_type, string destination_method_name,
bool usejump)
{
MethodInfo Source_Method = source_type.GetMethod (source_method_name, (BindingFlags)(60));
MethodInfo Destination_Method = destination_type.GetMethod (destination_method_name, (BindingFlags)(60));

if (Source_Method == null || Destination_Method == null)
return 404;

int Source_Base = Source_Method .MethodHandle.GetFunctionPointer ().ToInt32();
int Destination_Base = Destination_Method.MethodHandle.GetFunctionPointer ().ToInt32();

int offset_raw = Destination_Base - Source_Base;
uint* Pointer_Raw_Source = (uint*)Source_Base;

if (usejump)
{

*(Pointer_Raw_Source+0) = 0xE9909090;
*(Pointer_Raw_Source+1)= (uint)(offset_raw-8);
}
else
{
*(Pointer_Raw_Source+0) = 0x83ec8b55;
*(Pointer_Raw_Source+1) = 0xe89008ec;
*(Pointer_Raw_Source+2) = (uint)(offset_raw-12);
*(Pointer_Raw_Source+3) = 0x9090c3c9;
}

return 0;
}


nuff said.
#22
TL:DR - does not work as "entry" point, will be invoked before any other method in module, if no methods are invoked - no luck.

In order to test things, i checked some articles about "Module constructor C#" and found related content: http://einaregilsson.com/module-initializers-in-csharp/

Code below is "copy paste" with few additional lines.
namespace Rimgazer
{
    public static class module
    {
        public static void main()
        {
            Console.WriteLine(Environment.StackTrace);
            Console.WriteLine("LOOKS LIKE MODULE CCTOR");
        }
    }
}


In order to test how things will go, i "wrote" same loading 2 liner:

byte[] rawAssembly = File.ReadAllBytes("Rimgazer.dll");
Assembly asm = AppDomain.CurrentDomain.Load(rawAssembly);

Console.WriteLine (asm);

RuntimeHelpers.RunModuleConstructor (asm.GetModules ()[0].ModuleHandle);
Console.WriteLine ("BREAK");
asm.GetTypes ()[0].GetMethod ("main").Invoke (null, null);


RimWorld invoke no debugging, just "asm.GetTypes ()" and this invocation will not trigger module cctor.
#23
Help / Removing "combat slowdown" feature from RimWorld
November 05, 2015, 09:45:01 AM
Disclaimer:
black arts, version\platform dependant

I saw questions about "boring" combat slowdown zillion times, also I saw zillion explanations of game design by Tynan, still, if people asks, someone should give them what they want.

Generic reverse engineering method is "observation", actually "observation" is generic method of humanity, all known technology invented by observation of some kind or
related to results of previous observations.

First action we will perform is observation, we will force game into desired state and track clearly visible changes.
You can use this simple and yet not popular method for anything.

Most clear change is "stroked out" fast and very fast speeds, you just can't miss this change.

With some knowledge of unity API and (god bless) google we likely to discover DrawLineHorizontal method that perform "line rendering".
Also you can use "time" and or "speed" keys and or just bruteforce entire source of game (my favorite method, but it extremely time and energy consuming).

That method can be found inside TimeControls class that  performs most actions related to speed control.
But not every action, few things moved to other locations.

Condition related to drawing line is "Find.TickManager.slower.ForcedNormalSpeed".
That "condition" is boolean property of TimeSlower class.

From perspective of CLI property is instance method with name "get_ForcedNormalSpeed".
That method is compiler generated and hidden from view, also, due to control pass and inline limits, property is slower then direct access of field, that will be inlined.

ONLY action done by that method is returning or setting specific variable, nothing more, nothing less.

Most simple way to "remove" slowdown is changing that method into unconditional return of desired value.
But in our case we will redirect variable IO into different variable, this will allow to hook "slowdown", enable and disable it at any moment.

Probably i should bind hotkey for it or add menu checkbox, later...

All methods are stored in memory (obviously) in form of platform specific opcodes, in case of our target platform (windows64) opcodes are x86 assembler.
IL codes also stored, but, they used only for initial method compilation and later are ignored.

Its possible to change IL and force recompilation, but this will be explained later.

Invocation of GetFunctionPointer() over MethodInfo expose native pointer to x86 of that method.
Memory allocated for methods marked RWX ever after compilation is complete, this allows to rewrite method code at runtime.

payload of getter method is simple: loading variable reference into EAX, dereferencing EAX and returning result.

Variable reference is "hardcoded" into method and stored as part of opcode, it can be changed right here without any side effects.
Variable reference of "normal" types is exposed by "&" operator without any magic.

If you want reference to "managed type" you can read it from bytecode, calculate from class pool or just invoke __makeref undocumented IL code.
Under normal conditions you should never do it with managed types, you can screw garbage collection.

Lets begin:

            Log.Warning("x86 override test 2");
            Log.Warning("this mod will override TimeSlower.ForcedNormalSpeed");

            //getting pointer to method
            //double check binding flags, in other case game will fail with NPE
            byte* mpx_1 = (byte*)typeof(TimeSlower).GetMethod("get_ForcedNormalSpeed", BindingFlags.Instance | BindingFlags.Public).MethodHandle.GetFunctionPointer().ToPointer();

            //lazy init
            int ttz = 0;

            //read reference of our controller variable
            fixed(bool* key = &TIMESLOWEROVERRIDE)

            //cast reference into int
            ttz = (int)key;

            //just debug
            Log.Warning(ttz.ToString("X2"));

            //convert reference into byte array, this required to "reverse" bytes
            byte[] bytes = BitConverter.GetBytes(ttz);


            *(mpx_1 + 0) = 0xB8; //XOR MOV RAW
            *(mpx_1 + 1) = bytes[0]; //RAW WORD
            *(mpx_1 + 2) = bytes[1];
            *(mpx_1 + 3) = bytes[2];
            *(mpx_1 + 4) = bytes[3];

            *(mpx_1 + 5) = 0x8b; //XOR DEREFERENCE
            *(mpx_1 + 6) = 0;   //into itself
            *(mpx_1 + 7) = 0x90; //padding
            *(mpx_1 + 8) = 0x90;

            *(mpx_1 + 9) = 0xC3; //return

            Log.Warning("override complete");
            Log.Warning("have a nice day!");


Invoking given code at any moment will redirect time slowdown control into TIMESLOWEROVERRIDE variable making methods SignalForceNormalSpeed and SignalForceNormalSpeedShort used by engine obsolete.







#24
Well, this is about using x86 assembler directly (native assembly over c#).

Not a joke...

Mono runtime expose raw function pointer for any method (it will jit method on pointer request), with this pointer you can modify raw x86 assembly of that method via unsafe pointer operations.

        unsafe public sealed override void ResolveReferences()
        {
            Log.Warning("x86 override test 1");
            Log.Warning(TEST().ToString());

            byte* mpx_1 = (byte*)typeof(Redefine).GetMethod ("TEST", BindingFlags.Static | BindingFlags.Public).MethodHandle.GetFunctionPointer ().ToPointer();
           
            *(mpx_1 + 0) = 0xB8; //mov eax,0x0
            *(mpx_1 + 1) = 7;
            *(mpx_1 + 2) = 2;
            *(mpx_1 + 3) = 2;
            *(mpx_1 + 4) = 1;
            *(mpx_1 + 5) = 0xC3; //ret

            Log.Warning("x86 override test 2");
            Log.Warning(TEST().ToString());


            Log.Warning("have a nice day!");

            //StageA();
        }


Currently i dig mono sources for safe and easy method do pass control over methods, including methods crossing domains.

I need just few days to polish stuff, then, you will be allowed to hook\override non virtual methods of any type with any code.

Basic operations will be allowed to anyone, non standard - advanced CLI\assembler

1) You make your own implementation of specific method, signature must match, no other limits.

2) You invoke specific payload method, it will compile Jmp trampoline from target method to your own and modify memory.

3) In case of profiling style, it will reassemble target method as IL or x86 and place specific call into specific location as dynamic method.
compile delegate for that method and then compile Jmp trampoline from target method to delegate.

limits are:
i have no resources to support other platforms, x86 only
performance penalty in case of major additions to method code due to delegate use
memory leaks - delegates never unload
generic runtime stability loss, single ever minor error will cause odd effects instantly or some time later

Sample dll have not yet implemented classes, entire payload stored inside     
public class Redefine : Def
https://github.com/RawCode/Rimgazer



More "useful" sample:

invoking this code will allow to build inside areas marked as edge
            byte* mpx_1 = (byte*)typeof(GenGrid).GetMethod("InNoBuildEdgeArea", BindingFlags.Static | BindingFlags.Public).MethodHandle.GetFunctionPointer().ToPointer();
           
            *(mpx_1 + 0) = 0xB8; //mov eax,0x0
            *(mpx_1 + 1) = 0;
            *(mpx_1 + 2) = 0;
            *(mpx_1 + 3) = 0;
            *(mpx_1 + 4) = 0;
            *(mpx_1 + 5) = 0xC3; //ret


[attachment deleted due to age]
#25
Ideas / Kill list
September 07, 2014, 09:06:06 AM
Good old kill list with all kills made by pawn listed.

Actually this feature extremely easy to implement as mod \ addon, but i would like to see it in vanilla.
#26
Help / VS 2013 git hub integration in 11 steps
August 21, 2014, 04:51:52 AM
I see no reason to reinvent bicycle, everything already invented:
http://stackoverflow.com/a/20004092/2978478

QuoteOK this worked for me.
Open the solution in Visual Studio 2013
Select File | Add to Source Control

That creates a local GIT repository
Surf to GitHub
Create a new repository DO NOT SELECT Initialize this repository with a README

That creates an empty repository with no Master branch
Once created open the repository and copy the URL (it's on the right of the screen in the current version)
Go back to Visual Studio
Open Team Explorer
Select Home | Unsynced Commits
Enter the GitHub URL into the yellow box
Click Publish
Select Home | Changes
Add a Commit comment
Select Commit and Push from the drop down

Your solution is now in GitHub

After simple and easy procedure, you can work with git without any additional applications right from "Team Explorer view".
#27
Help / Arbitrary XML\DLL definitions
August 21, 2014, 04:44:12 AM
This is extended answer to:
http://ludeon.com/forums/index.php?topic=5610.0

My original answer was ignored:
Quote
You must extend thing def in your code with fields you like and define your thing def, not basic type.
for no good reason.

1) If you want to have arbitrary define type, you MUST extend Def.
Classes not extending Def are ignored by database assembler.
Extending ThingDef or any other "second level" defs require to use "Class" modifier, or base type constructor will be used.

2) You dont need to nest your type inside "ThingDefs" - you must define separate category, format is type name + s.
(note, ALL CAPS names will fail)
In other case database assembler will fail to find your def.

In case of "Class" modifier - def must be hosted in "base" folder, if Class points to type not accessable due to any reason - default type will be used, any additional fields will be ignored

Test type:

    [EventListener("instance", "entry")]
    public class typez : Def
    {
        public string testvalue = "NOT DEFINED";
        public static typez instance;

        public typez()
        {
            instance = this;
        }

        public static void entry()
        {
        }

        [EventHandler(EventPriorityEnum.LOW)]
        public void testa(GameStartedEvent e)
        {
            Log.Warning(testvalue);
        }

    }

do require Rimgazer API to work.

Def folder will be Defs\typezs\arbitraryname.xml

3) XML def follow same rules as folders do:


<?xml version="1.0" encoding="utf-8" ?>
<typezs>
<typez>
<testvalue>REPLACED BY DEFINE</testvalue>
</typez>
</typezs>


Running such mod will show "REPLACED BY DEFINE" on game start.

In order to test code without running game and without usage of API - static initializer may be used.
It will be invoked early (or not invoked if something is wrong).
#28
Help / [Rimgazer API] Friendly fire disabler
August 17, 2014, 09:10:55 AM
Simple and effective mod - it completely disable *true* friendly fire.
Your colonists (and pirates too) wont harm each other under any conditions, but still can harm "neutral" visitors or animals.
Insane pawns also subject to damage from attacks.

[attachment deleted by admin: too old]
#29


Done by implementing Attribute and marking types with it:

https://github.com/RawCode/Rimgazer/blob/master/PersistentCommentAttribute.cs

    [PersistentComment("This is comment that visible in decompiled classes")]
    public class PersistentCommentAttribute : Attribute
    {
        public PersistentCommentAttribute(string PersistentCommentData)
        {
        }
    }


This allow to distribute mods as single assembly and still provide sourcecode.
#30
Bugs / [532][Balance relate] Animal insanity in forest
August 16, 2014, 07:04:45 AM
Probably this already reported, but, my 3 IRL hours colony was wiped by 60 squirrels!


I done this event before, one of my colonist with speed boost ran around towers for few minutes and towers wiped squirrels, but second time all my colonists were trapped inside cave with NO chance to survive.

#31
Help / [tech][wip] Rimgazer event driven API extension
August 16, 2014, 04:46:54 AM
Source code:
https://github.com/RawCode/Rimgazer

This is event driven framework (API) for RimWorld.

List of supported events:

GameStarted\Saved\Loaded\Event
FirstTick
GenericTick
Unit(Pawn)Damaged

Replace:
def-Human

[attachment deleted by admin: too old]
#32
If pawn damaged by tower explosion, this will count as hostile action and will cause faction to go hostile.

If pawn got fire and colonists try to beat that fire - again counted as hostile action.

Random shots also counted as hostile action but this OK.
#33
Generation of runtime defs and spawning things defined at runtime is perfectly fine.
Diablo like drops and mobs are possible.

Red deer of infernal death - no problem.
Murdering holy grenade of destruction - here you go.
Unlimited level upgrades - fast and easy.

Perfectly fine as long as you not going to save that game and load it later, because it will attempt to resolve everything before you will get a chance to regenerate all runtime defs you need.

Actually you can hack into loading process, but this very very version specific and probably platform specific.

Also its possible to define 100500 "abstract" defs, that will be filled with data later (currently i am going to implement stuff this way, by managing pool of runtime defs) but garbage collection issue is raised and such system feature huge overhead.

Why bug, because there is no trycatch section in few locations of code, this cause complete failure in case of missing defs without any chance of recovery.

How i see fast easy and no cost support of runtime defs (this is how minecraft forge solve references missing from game\world):

1) If game is failed to load some object due to missing def or any other reason, that object is placed to *dead* list with error message attached, without ruining main thread by exception.
Good objects initialized instantly.

2) After all other objects are loaded *dead* list loaded again.
3) Objects that managed to load (probably other object generated required def or altered some variable required) removed from list and initialized.
4) Process repeats as long as no objects left *dead* list after iteration.

5) After *dead* list is finalized - alive objects granted opportunity to inspect list of dead objects and change\edit objects or list itself.
Or just store debug data or sent bug report.

After that all invalid objects simply removed.
#34
If developer forgot to set defname for any object defined by mod, it will recieve "random" name, everything will go smooth but...

That random name NOT saved and on attempt to load that savegame from such mod, game will fail hard without any warning on load, on save or on startup.

#35
Issue is simple, types that extends MapComponent will be constructed two times on savegame loading.

First "wave" of constructed components then will be replaced by components created by savegame loader, both constructions do happen on Scribe.mode.LoadingVars.

This issue do not affect base game, but require ugly lines in mod's code to overcome and may cause issues later with other types of objects that load in similar manner.
Any code in constructor invoked two times and may corrupt object state without any warning.
#36
All credits go to original author
http://ludeon.com/forums/index.php?topic=4554.0

This version feature exactly same mod (cropped a bit at this moment) embedded into vanilla GUI.
Actually this completely useless and more tech demo\sample then actual mod.

Does not use world generation exploit, does not interfere with dev mode, compatible with all known to me mods.

http://youtu.be/tLlKHD3SqYQ

[attachment deleted by admin: too old]
#37
This mod uses unsafe stuff, it may not harm your computer or game, but likely to corrupt savegames, use backups (actually it work only on new games and wont corrupt anything, but still use backups).

What this mod does and how:

1) Using cctor feature of c# it injects arbitrary code into game at preinit stage, before game actually is started:

        static Loader()
        {
            ///Log.Error("<CINIT>(..cctor) Section invocation ((static)Type Constructor)");
            Thread branchA = new Thread(new ThreadStart(Loader.watchInternalState));
            branchA.IsBackground = true;
            main = Thread.CurrentThread;
            branchA.Start();
            //Log.Warning("THREAD STARTED");
        }


2) Separate thread used to monitor state of internal objects (and cause exceptions at random due single threaded nature of rimworld and lack of syncblocks):


                    //Log.Warning("CHECK INITTERD");
                    if (fz.TopLayer is Page_MainMenu)
                    {
                        //Log.Warning("CHECK PASSED");
                        fz.Add((Layer)new MainMenuImpl());
                    }


3) In our case it monitor what screen currently is shown, in order to keep resources check performed with delay:


                Thread.Sleep(1024);
                if (!Application.isPlaying)
                    break;
                Thread.Sleep(1024);


4) MainMenuImpl is reimplementation* of vanilla class that looks just like vanilla class, but act a bit differently:


due to 2 seconds delay you still can hit "normal" button, this by design.

5) All other windows also reimplemented and linked. (not all actually and linked one way only).

6) Final window - character creation have custom payload that alter colonist generation:


Enjoy.


[attachment deleted by admin: too old]
#38
Unfinished / [WIP][need artist] Necromancy!
August 08, 2014, 07:59:43 AM
Now you can bring dead back to life.
This mod is about special grave that rise from dead anyone who was placed inside.
Rised units keep all stats skills and stuff they had before death.

Current version is tech demo, final version of mod will feature slow process what will require immerse amount of energy, based on damage received and time passed from moment of death.
Also ancient crypt will spawn on map with extremely powerful (but somewhat dead) creatures that can be returned to life.

Inspired by
http://stargate.wikia.com/wiki/Sarcophagus
and random zombie movies

I will eventually draw sprites self, but some help will be accepted.
I need two sprites - first - satanic altar (it will be fueled with bodies of other creatures)
second - hightech - fueled by energy.

Basic version of mod included.
Source code included.

[attachment deleted by admin: too old]
#39
This early development version but, it working just as designed.

At this moment "injection" done by additional "monitor" thread, this subject to change, perfectly - by original game developer.

there is only single def at play:


<?xml version="1.0" encoding="utf-8" ?>
<Loaders>
<Loader>
</Loader>
</Loaders>


this def will perform loading of *main* type of assembly, allowing to inject code at early stages of game.

payload code is


public class Loader : Def
    {
        static Loader()
        {
            Log.Error("<CINIT>(..cctor) Section invocation ((static)Type Constructor)");
            Thread branchA = new Thread(new ThreadStart(Loader.watchInternalState));
            branchA.Start();
//we start new thread here to monitor game activity and field change, this done in place of bytecode injection.
        }

        static void watchInternalState()
        {
            for(;;) //infinite loop
            {
                try //just in case, normal exceptions wont show up in console
                {

                    if (Find.RootMap == null) //as long as map not initialized we do nothing
                        continue;

                    Thread.Sleep(100); //when map is initialized, we wait to ensure object init and perform payload
                    //throw GameInitializeEvent and handle all mods that listen to it NYI
                    Find.Map.storyteller.weatherDecider = new WeatherDeciderImpl();
                    Log.Error("Weather Decider is replaced;");
                    break; //we no longer need this thread, we break loop and terminate it
                }catch( Exception E)
                {
                    Log.Error(E.ToString());
                }
            }
        }
    }


c# unlike java allows to override only methods marked virtual, this is severe limitation to hacking.
since WeatherDecider still have single virtual method - we override it.


    public class WeatherDeciderImpl : WeatherDecider
    {
        protected override WeatherDef NextWeather() //only method that can be "hooked"
        {
            Log.Error("Virtual method invocation");
            return DefDatabase<WeatherDef>.AllDefs.First(); //first def is "clear" weather, it's possible to define any other weather, including permanent dry thunderstorm or cycle weather in predefined order
        }
    }
#40
I know about EULA and generic international law, nothing can stop me from doing it actually, but can i state on this forum directly "i have decompiled game and found issue in type A here is a fix" or "i know how to improve method A of type B there is my implementation".