boo-lang / boo

The Boo Programming Language.
BSD 3-Clause "New" or "Revised" License
858 stars 146 forks source link

unmanaged struct Context64 #204

Closed physics-sec closed 4 years ago

physics-sec commented 4 years ago

Hi! I want to create a struct in Boolang, the struct is called Context64 from GetThreadContext This is the struct in C# (from https://github.com/illumen/Bleak/blob/master/Bleak/Etc/Native.cs):

        [StructLayout(LayoutKind.Sequential, Pack = 16)]
        internal struct Context64
        {
            private readonly IntPtr P1Home;
            private readonly IntPtr P2Home;
            private readonly IntPtr P3Home;
            private readonly IntPtr P4Home;
            private readonly IntPtr P5Home;
            private readonly IntPtr P6Home;

            internal ContextFlags Flags;
            private readonly int MxCsr;

            private readonly short SegCs;
            private readonly short SegDs;
            private readonly short SegEs;
            private readonly short SegFs;
            private readonly short SegGs;
            private readonly short SegSs;

            private readonly int EFlags;

            private readonly IntPtr Dr0;
            private readonly IntPtr Dr1;
            private readonly IntPtr Dr2;
            private readonly IntPtr Dr3;
            private readonly IntPtr Dr6;
            private readonly IntPtr Dr7;

            private readonly IntPtr Rax;
            private readonly IntPtr Rcx;
            private readonly IntPtr Rdx;
            private readonly IntPtr Rbx;
            private readonly IntPtr Rsp;
            private readonly IntPtr Rbp;
            private readonly IntPtr Rsi;
            private readonly IntPtr Rdi;
            private readonly IntPtr R8;
            private readonly IntPtr R9;
            private readonly IntPtr R10;
            private readonly IntPtr R11;
            private readonly IntPtr R12;
            private readonly IntPtr R13;
            private readonly IntPtr R14;
            private readonly IntPtr R15;
            internal IntPtr Rip;

            private readonly SaveFormat DummyUnionName;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)]
            private readonly M128A[] VectorRegister;
            private readonly IntPtr VectorControl;

            private readonly IntPtr DebugControl;
            private readonly IntPtr LastBranchToRip;
            private readonly IntPtr LastBranchFromRip;
            private readonly IntPtr LastExceptionToRip;
            private readonly IntPtr LastExceptionFromRip;
        }

I translated it in the following way:

[StructLayout(LayoutKind.Sequential, Pack : 16)]
struct Context64:
    P1Home as IntPtr
    P2Home as IntPtr
    P3Home as IntPtr
    P4Home as IntPtr
    P5Home as IntPtr
    P6Home as IntPtr

    Flags as ContextFlags
    MxCsr as int

    SegCs as short
    SegDs as short
    SegEs as short
    SegFs as short
    SegGs as short
    SegSs as short

    EFlags as int

    Dr0 as IntPtr
    Dr1 as IntPtr
    Dr2 as IntPtr
    Dr3 as IntPtr
    Dr6 as IntPtr
    Dr7 as IntPtr

    Rax as IntPtr
    Rcx as IntPtr
    Rdx as IntPtr
    Rbx as IntPtr
    Rsp as IntPtr
    Rbp as IntPtr
    Rsi as IntPtr
    Rdi as IntPtr
    R8 as IntPtr
    R9 as IntPtr
    R10 as IntPtr
    R11 as IntPtr
    R12 as IntPtr
    R13 as IntPtr
    R14 as IntPtr
    R15 as IntPtr
    Rip as IntPtr

    DummyUnionName as SaveFormat

    [MarshalAs(UnmanagedType.ByValArray, SizeConst : 26)]
    VectorRegister as (M128A)
    VectorControl as IntPtr

    DebugControl as IntPtr
    LastBranchToRip as IntPtr
    LastBranchFromRip as IntPtr
    LastExceptionToRip as IntPtr
    LastExceptionFromRip as IntPtr

yet, when I read the Rip, is 0 for all the threads, which makes no sense.

(all the inner structs like SaveFormat and M128A are defined as well) (I had to replace [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] with [MarshalAs(UnmanagedType.ByValArray, SizeConst : 26)], because the compiler complained)

this is how i defined GetThreadContext:

[DllImport("kernel32.dll")]
def GetThreadContext(threadHandle as IntPtr, ref context as Context64) as bool:
    pass

Is there anything obvious that I am doing wrong? I am pretty sure that the struct is not well defined, and that is why the value in the Rip makes no sense. If the struct makes sense in as far as Boolang is concerned, then dismiss the issue.

Thanks in advance!

masonwheeler commented 4 years ago

I don't see any obvious problem. So either there's something wrong with your struct definition, or there's something wrong with the function call, or there's something wrong with the original code. So try this:

At one of these three points, it should break. That should tell you where the problem lies.

physics-sec commented 4 years ago

That is a great idea, thank you!

physics-sec commented 4 years ago

Well I am using this repo now: https://github.com/pwndizzle/c-sharp-memory-injection/blob/master/thread-hijack.cs And I can confirm it works properly. Same issue if I translate the structs/enums into my Boo script

I am not sure how to add that project to my Boo script as a dependency, do you have any resource or example I can see? I don't wan't to waste much of your time

The idea of adding external dependencies to my Boo scripts sounds great. So far, I have been loading the .net assembly of some compiled program and then invoking the methods I want. I can just try that, but not sure how much informations it would give us about the issue

Boo is truly amazing, especially the compile from memory feature Is like .net python, I love it

physics-sec commented 4 years ago

Ok, turns out that the struct was well defined, the issue was how I was calling GetThreadContext. I needed to add the line in the middle:

        context = CONTEXT64()
        context.ContextFlags = CONTEXT_FLAGS.CONTEXT_FULL
        success = GetThreadContext(threadHandle, context)

Sorry to wast your time!

masonwheeler commented 4 years ago

Good to hear you got it working! 😄