4

i have this piece of asm code in a string attribute:

mov [ecx+ebx*4+10],ff
jmp client.dll+3A8D96

before getting into what i'm trying to achieve, first i will change client.dll+... into it's final address of course.

Now what i'm currently trying to achieve is either:

  • Convert that piece of asm code into it's equivalent bytes so i can write back these bytes into memory after changing them using winapi ..

  • Or somehow write that string's content in an allocated memory , which kind of seems impossible without converting it to bytes .. idk

I dont know if possible or not but i also have got this idea:

  • make a dll in c++ that will have a function that can be imported from my c# app
  • make use of any posible ways to achieve my goal by passing the asm opcode and allocated memory adress as Parameters (not a c++ expert) but i know that inline asm is possible in c++ .

Keep in mind that the ASM code given in this post is just to demonstrate what i'm trying do, it will be actually changing a lot, i hope you get the idea.

0 x 5 4 4 D
  • 177
  • 1
  • 13
  • Wanting to run inline ASM in C++ is usually a bad idea in the first place. – Jesper Juhl Feb 29 '20 at 19:03
  • @JesperJuhl i just felt like putting that there , but thanks for the info . – 0 x 5 4 4 D Feb 29 '20 at 19:08
  • 1
    When I do assembly programming, I put my code in a `*.ASM` file and run it through my assembler and linker. – Eljay Feb 29 '20 at 19:19
  • @Eljay I also thought about that i just forgot to say that in the post , a perfect way will be to copy my string's content into a file.asm ans exec it , but still that wont help with writing the asm code into the new allocated memory , however i think it will be possible to get the bytes ? **:thinking:** – 0 x 5 4 4 D Feb 29 '20 at 19:26
  • Using C# for what you are describing seem like a quite a crazy plan... You may want to consider just C++ for such work... – Alexei Levenkov Feb 29 '20 at 20:20
  • 1
    You haven't shown opcodes in your post, you've shown asm source code. But then you talk about extracting asm from a process at runtime. Normal processes don't contain any asm strings in memory, they contain machine code. And you say you want to convert "asm to its equivalent bytes". That's what an *assembler* does (text->binary), but then you describe that as *disassembling*. So it's not even clear what you want: just execute some machine code you copied out of another process? Fine, copy it into an executable page (`VirtualAlloc` or `mmap`). You'd have to relocate any relative jumps... – Peter Cordes Feb 29 '20 at 20:59
  • @PeterCordes cleared out some stuff , poor english skills maybe ? in brief : how to convert such "MOV eax,1" **instruction** into it's equivalent bytes inside a c# / c++ program . Hope you've got a solution to that , without making my own Disassembler. – 0 x 5 4 4 D Feb 29 '20 at 21:07
  • If it's a compile-time-constant string, you can use inline asm to use the same assembler that builds the compiler output. Otherwise there are a few assemblers that you can include as a library. Some of them, like LLVM, are designed for use-cases that include *executing* the resulting machine-code bytes. Others are simpler and just give you the bytes. IDK if any let you use symbol names from your own process, and symbol names from another process would be very unlikely. – Peter Cordes Feb 29 '20 at 21:11

3 Answers3

2

Use Keystone's C# bindings to convert your assembly into bytes. It's very easy to use, you give it a string and it gives you an array of bytes that represent the assembly code you gave for input:

using Keystone;

using (Engine keystone = new Engine(Architecture.X86, Mode.X32) { ThrowOnError = true })
{
    ulong address = 0;

    keystone.ResolveSymbol += (string s, ref ulong w) =>
    {
        if (s == "_j1")
        {
            w = 0x1234abcd;
            return true;
        }

        return false;
    };

    EncodedData enc = keystone.Assemble("xor eax, eax; jmp _j1", address);

    enc.Buffer.ShouldBe(new byte[] { 0x00 });
    enc.Address.ShouldBe(address);
    enc.StatementCount.ShouldBe(3);
}

To convert a Cheat Engine Code Injection script to a C# code, you want to do external detouring. Use VirtualAllocateEx() to get space in the target process, write your shell code you created with KeyStone into memory using WriteProcessMemory, then perform your detour to detour execution flow to your shellcode you injected.

You will need to resolve relative jumps and all relative addresses manually in your detour function.

Alternatively you can use CreateRemoteThread() to execute code in the target process in a new thread rather than via a detour, depending what you want to do.

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
GuidedHacking
  • 3,628
  • 1
  • 9
  • 59
1

If you are using c# i suggest u use wrappers for Write process memory and Import the necessary dlls and etc and get raw bytes of your asm opcodes and manipulate them to your own accord

if you are using c++ you can just use the functions without needing to fetch the wrappers and etc; most of the functions are there in C++ libs

if you looking for something like cheat engine codecave (aob injection with a jump and jumpback) id consider u invest some time for learning somethings about memory manipulating / allocating memory / how asm work in general, after that u can just mess with memory at ease

also for internal dlls using c++ you need to use raw bytes, if i recall correctly they removed the asm functionality for codecaves and such from visual studio 2010 and restricted it only to enterprise version or something

also if you thinking about using this opcode as it is jmp client.dll+3A8D96 that would be a really bad idea if u know asm, if its a near jump its not a big deal but these offsets could change from time to time

"\xFE\xC8\x5B\x23\xC1"

this is just an example how i use bytes for my codes, there are some good tutorials on youtube you should check them out

Agntluck
  • 11
  • 2
  • uhm , That does not answers my question .. all u've said are basic stuff that i already know to do since ages . but thanks for trying i guess .. – 0 x 5 4 4 D Feb 29 '20 at 22:09
  • 1
    Convert that piece of asm code into it's equivalent bytes so i can write back these bytes into memory after changing them using winapi .. for this u can use 1) Online website and do it manually 2) If you want to do it programmatically there are disassemblers coded in c++ use ones source with string parsing and modify to your accord 3) u can just use the cheat engine on any program or the program u gonna manipulate to get the raw bytes – Agntluck Feb 29 '20 at 22:19
  • Said that the operand code i gave in the example was just for demo , it will be a dynamic , so do that manually is null . I did not said anything about debuggers or cheat engine so let that away :) . and yes what im asking is how to do it programmatically , is what you said is true Can you provide examples on these disassemblers and how to use one ? – 0 x 5 4 4 D Feb 29 '20 at 22:24
  • 1
    this is one of them https://github.com/skywind3000/asmpure also look through this thread https://stackoverflow.com/questions/17001094/c-library-x86-x64-assembler I had a better one but can't remember the details since ive moved to raw bytes myself for a long time now – Agntluck Feb 29 '20 at 22:43
  • cheers Mate ! Very Appreciated for your efforts , Very usefull refs ! – 0 x 5 4 4 D Mar 01 '20 at 00:40
1

This is far from your full problem (C#...) but it could give you some clues.

This example is done in C with gcc on Linux-64; you may have to adapt it on your platform.

The first step was to write a function with some inline assembly (gnu-asm syntax) in order to see how it looks with objdump (it is never called actually).
The trick to jump to a constant address was found here: https://stackoverflow.com/a/53876008/11527076

After that we have to create an executable memory segment and fill it with bytes inspired from the previous function (thanks to objdump).
If the only thing that may be changed is the address, then we just overwrite this address in the previous code.
In this example, the address of another function is used for this purpose.

Then this executable memory segment can be considered as a function (hum... hopefully) and we use it through a function pointer.
And it seems to work!

The only problem I can see is the instruction movb $0xff,0xa(%ecx,%ebx,4) which does something bad because I don't know exactly what the registers should contain.
I decided to replace this instruction by six nop to occupy the same place and keep this example similar to the original problem.
(I suppose that in the context of your problem these registers will have a relevant value).

/**
  gcc -std=c99 -o prog_c prog_c.c \
      -pedantic -Wall -Wextra -Wconversion \
      -Wc++-compat -Wwrite-strings -Wold-style-definition -Wvla \
      -g -O0 -UNDEBUG -fsanitize=address,undefined
**/

#undef __STRICT_ANSI__ // for MAP_ANONYMOUS
#include <sys/mman.h>

#include <stdio.h>
#include <string.h>
#include <stddef.h>

void
target_function(void)
{
  printf("~~~~ %s ~~~~\n", __func__);
}

void
inline_asm_example(void)
{
  __asm__ __volatile__(
    "\tnop\n"
    "\tmovb   $0xff,0xa(%ecx,%ebx,4)\n"
    "\tjmpq   *0x0(%rip)\n"
    ".quad 0xAA00BB11CC22DD33\n");
  // the jump relative to rip is inspired from
  // https://stackoverflow.com/a/53876008/11527076
}

int
main(void)
{
  // create an executable page
  void *page=mmap(NULL, 6+6+8,
                  PROT_READ|PROT_WRITE|PROT_EXEC,
                  MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
  if(page==MAP_FAILED)
  {
    fprintf(stderr, "cannot allocate memory page\n");
    return 1;
  }

  // initialise code pattern
  //   objdump --disassemble=inline_asm_example prog
  char *code_pattern=(char *)page;
#if 0 // this instruction causes something wrong
  memcpy(code_pattern+0,
    "\x67\xc6\x44\x99\x0a\xff", 6); // movb   $0xff, 10(%ecx,%ebx,4)
#else // use some useless instructions instead
  memcpy(code_pattern+0,
    "\x90\x90\x90\x90\x90\x90", 6); // 6x nop
#endif
  memcpy(code_pattern+6,
    "\xff\x25\x00\x00\x00\x00", 6); // jmpq   *0x0(%rip)

  // insert into the pattern the address we want to jump to
  ptrdiff_t target_address=(ptrdiff_t)target_function;
  memcpy(code_pattern+6+6, &target_address, sizeof(target_address));

  // consider the code pattern as a function
  void (*fnct_ptr)(void)=NULL;
  memcpy(&fnct_ptr, &code_pattern, sizeof(code_pattern));

  // here we go
  printf("about to do something I will probably regret...\n");
  fnct_ptr();
  printf("ah? it was not so painful after all!\n");

  // let's forget everything about that
  munmap(code_pattern, 6+6+8);
  return 0;
}
prog-fh
  • 13,492
  • 1
  • 15
  • 30