Click here to Skip to main content
Click here to Skip to main content

Execute Native Code From .NET

By , 29 Aug 2004
 

Introduction

If you want to prevent your program from being cracked by hackers, you can use native code. You can cipher/decipher this code, or it may be self-modifying code for more safety. Now, I'll show how you can execute such native code from your C# programs.

Source code

This example retrieves CPU information.

private void button1_Click(object sender, System.EventArgs e)
{
  // native function's compiled code

  byte[] proc = new byte[] {

               0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x00, 0x53, 0x51, 
               0x52, 0x57, 0x8B, 0x7D, 0x08, 0x33, 0xC0, 0x0F, 
               0xA2, 0x89, 0x07, 0x89, 0x5F, 0x04, 0x89, 0x57, 
               0x08, 0x89, 0x4F, 0x0C, 0xB8, 0x01, 0x00, 0x00, 
               0x00, 0x0F, 0xA2, 0x89, 0x47, 0x10, 0x89, 0x57, 
               0x14, 0xB8, 0x00, 0x00, 0x00, 0x80, 0x0F, 0xA2, 
               0x3D, 0x00, 0x00, 0x00, 0x80, 0x72, 0x0A, 0xB8, 
               0x01, 0x00, 0x00, 0x80, 0x0F, 0xA2, 0x89, 0x57, 
               0x18, 0x5F, 0x59, 0x5B, 0x5A, 0x8B, 0xE5, 0x5D, 
               0x33, 0xC0, 0xC2, 0x04, 0x00
                                  };
  UInt32 funcAddr = VirtualAlloc(0, (UInt32)proc.Length, 
                    MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  Marshal.Copy(proc, 0, (IntPtr)(funcAddr), proc.Length);
  IntPtr hThread = IntPtr.Zero;
  UInt32 threadId = 0;
  // prepare data

  PROCESSOR_INFO info = new PROCESSOR_INFO();

  IntPtr pinfo = 
    Marshal.AllocHGlobal(Marshal.SizeOf(typeof(PROCESSOR_INFO)));

  Marshal.StructureToPtr(info, pinfo, false);

  // execute native code

  hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);

  WaitForSingleObject(hThread, 0xFFFFFFFF);
  // retrive data

  info = (PROCESSOR_INFO)Marshal.PtrToStructure(pinfo, 
                              typeof(PROCESSOR_INFO));

  Marshal.FreeHGlobal(pinfo);
  CloseHandle(hThread);
  VirtualFree((IntPtr)funcAddr, 0, MEM_RELEASE);
}

private UInt32 MEM_COMMIT = 0x1000;

private UInt32 PAGE_EXECUTE_READWRITE = 0x40;

private UInt32 MEM_RELEASE = 0x8000;

[DllImport("kernel32")]
private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr, 
     UInt32 size, UInt32 flAllocationType, UInt32 flProtect);

[DllImport("kernel32")]
private static extern bool VirtualFree(IntPtr lpAddress, 
                      UInt32 dwSize, UInt32 dwFreeType);

[DllImport("kernel32")]
private static extern IntPtr CreateThread(

  UInt32 lpThreadAttributes,
  UInt32 dwStackSize,
  UInt32 lpStartAddress,
  IntPtr param,
  UInt32 dwCreationFlags,
  ref UInt32 lpThreadId

  );
[DllImport("kernel32")]
private static extern bool CloseHandle(IntPtr handle);

[DllImport("kernel32")]
private static extern UInt32 WaitForSingleObject(

  IntPtr hHandle,
  UInt32 dwMilliseconds
  );
[DllImport("kernel32")]
private static extern IntPtr GetModuleHandle(

  string moduleName

  );
[DllImport("kernel32")]
private static extern UInt32 GetProcAddress(

  IntPtr hModule,
  string procName

  );
[DllImport("kernel32")]
private static extern UInt32 LoadLibrary(

  string lpFileName

  );
[DllImport("kernel32")]
private static extern UInt32 GetLastError();

[StructLayout(LayoutKind.Sequential)]
internal struct PROCESSOR_INFO 
{
  public UInt32 dwMax; 
  public UInt32 id0;
  public UInt32 id1;
  public UInt32 id2;

  public UInt32 dwStandard;
  public UInt32 dwFeature;

  // if AMD
  public UInt32 dwExt;
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Maxim Alekseykin
Team Leader
Russian Federation Russian Federation
Member
MCAD
 
Now is looking for remote job.
 
- C++/C#, VB/VBA, SQL Server/Access databases.
- automatic testing, code review
- performance tuning
max.uk2005@gmail.com
-

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralPROCESSOR_INFO SIZE!!!!memberfuck bill gates22 Jan '09 - 0:49 
on WinCe 5.0
PROCESSOR_INFO has 576 bytes length Smile | :)
and a lot of WCHAR fields each 40 chars Smile | :)
Questionhow I do to execute a EXE from inside my application?membersebastiannielsen12 Jul '08 - 2:43 
I have tried with placing the raw bytes from any EXE, inside the "proc" array, and then using your code to execute it, but I only get "WindowsApplication1 has encountered a problem and needs to quit" message with that send or don't send buttons.
 
I want to execute a raw EXE stored in a byte array, without writing it to disk and using Shell(). Like putting it in memory and executing it in the same way as the EXE on disk would be double clicked.
AnswerRe: how I do to execute a EXE from inside my application?memberMaxim Alekseykin14 Jul '08 - 3:04 
Hi Sebastian,
 
the problem you've encountered is not too simple Smile | :) in my example the 'proc' array shouldn't contain any calls of any external api including win32 api. You can quite simply modify it to call some of them but any way it can't load and execute an independent exe. My next project and the article might be exactly about this Smile | :) it'll load any type (either managed or native) exe into the memory and execute it.
 
Regards.
GeneralWhere did you get the proc binarymemberI like it2 Nov '05 - 6:18 
Confused | :confused: How we can get the proc binary?
 
Thanks,

GeneralRe: Where did you get the proc binarymemberMaxim Alekseikin2 Nov '05 - 9:14 
for example:
- write procedure in C++ or assembly language
- compile your programme
- see your code under debuger in dissassembly window of your VS
- copy byte code of your procedure
- a bit edit this code
 
you can find more information about how to get bynary code from Internet.
QuestionHow to use CStringArray in C# using p/invokemembershusong18 Apr '05 - 15:50 
In a regular dll using shared MFC dll,there is a variable which type is CStringArray.
In c# project , i want to get the string array which length is inconstant.
 
1, I build a Regular Dll using shared MFC dll named MFCDLL.dll as follows:
 
extern "C" void PASCAL EXPORT GetValues(CStringArray & stringArray)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString a = "a";
CString b = "b";
 
stringArray.Add(a);
stringArray.Add(b);
}

 
2,build a c# console project named text.exe as follows:
using System;
using System.Runtime.InteropServices;
 
namespace CSharpProject
{
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
class CStringArray{
public string[] m_pData;
int m_nSize;
int m_nMaxSize;
int m_nGrowBy;
}
 
class Class1
{
[DllImport("MFCDLL.dll", CharSet=CharSet.Auto)]
public static extern void GetValues(out CStringArray strarr);
 
[STAThread]
static void Main(string[] args)
{
CStringArray stringArray = new CStringArray();
GetValues(out stringArray); // thow exception
}
}
}

3, Copy MFCDLL.dll to the directory of text.exe.
4,double press text.exe ,but program throws exception:System.ExecutionEngineException. When debugging the text.exe,variable:stringArray is undefined value.I think maybe there is some problem with the structure of class CStringArray.
 
Thank you very much.
AnswerRe: How to use CStringArray in C# using p/invokememberMaxim Alekseikin, MCAD19 Apr '05 - 1:11 
"extern "C" void PASCAL EXPORT GetValues(CStringArray & stringArray)"
First, why PASCAL? use __stdcall.
 
"public string[] m_pData;"
Second, why string[]? use char[] or string
 
[DllImport("MFCDLL.dll", CharSet=CharSet.Auto)]
public static extern void GetValues(out CStringArray strarr);
 
use right CallingConvention value.
 
if I have time I'll try to resolve your problem.
Best regards.
GeneralRe: How to use CStringArray in C# using p/invokemembershusong19 Apr '05 - 16:16 
First,in MFC
#define PASCAL __stdcall
Second,in MFC,
CStringArray is an array of string,so, defining public string[] m_pData;
 
if you can debug my examples codes, you can find out something wrong.
 
Thank you for your answer.
 
Have a good day.
Alex
China
GeneralLegacy plug-insmemberHarkos8 Sep '04 - 9:13 
Hi Maxim,
 
I've been working on a way to use legacy plug-ins (from Win32 DLLs) into .NET and thanks to your article I came up with a great idea to accomplish this using 100% managed code. Big Grin | :-D
 
If anyone is also interested, you can visit my article about this solution here.
 
[]'s
Harkos
---
"Money isn't our god, integrity will free our soul."
Cut Throat - Sepultura
GeneralInteresting TechniquememberLim Bio Liong30 Aug '04 - 18:57 
I see that you are basically trying to embed x86 executable code into your program and then directly execute it (by making it the startup function of a thread).
 
This is an interesting way of hiding some functionality from prying eyes (who use tools like ILDASM, etc). I see some usage of this in classes that need custom de-serialization where some fields of a class (e.g. Credit Card Numbers, Passwords, etc) need to be re-constructed via some algorithm (as opposed to direct value-setting).
 
It would be very interesting to see if we can embed .NET IL into a byte array and then executing the IL in similar ways. I also suggest researching into stuff like CodeDom.
 
Best Regards,
Bio.

GeneralRe: Interesting TechniquememberMaxim Alekseikin30 Aug '04 - 22:09 
I'm thinking about IL.
CodeDom can create file on a disk. But we need an executable code in a memory. now I dont know a way to execute code in memory in .Net Frown | :(
GeneralGood Technique (for me!)sussMarcello Cantelmo30 Aug '04 - 10:41 
Only who has programmed in assembler x86 can appreciate these potentialities that are not previewed in way directed from the .net compiler
 
for example: with a ulterior (hide) technique in my crypter I have even implemented a api's hooker to stop a breakpoint on execution of a debugger Wink | ;) ...only our creativity!
 
regards,
Marcello
 
www.cantelmosoftware.com (in continuous modernization)
 

My last article on CodeProject: http://www.codeproject.com/dotnet/StackCrypt.asp
 
Nothing is Impossible if Not Tests the Absurdity
GeneralRe: Good Technique (for me!)memberMaxim Alekseikin30 Aug '04 - 22:22 
I can create such code in assembler and in VC++. this tools generate good machine code, which we can cut from binary file.
Your idea about our own virtual stack machine Smile | :) to execute code from the stack is good. May be I'll be able to integrate both these technics.
GeneralRe: Good Technique (for me!)sussMarcello Cantelmo30 Aug '04 - 23:30 
hi Maxim,
 
in fact, with my "StackCrypt" (with some modification) you can, also, generate to runtime (therefore a inside obfuscator) the code asm to send to the thread...
 
not enough the decompilation of the code... you must also reconstruct the entire algorithm Wink | ;)
 
regards,
Marcello

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 30 Aug 2004
Article Copyright 2004 by Maxim Alekseykin
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid