Jump to content






Photo

Special case of loaders for stubborn packed applications

Posted by Kurapica , 09 February 2015 · 2,004 views

Hi

This is my first blog post, It's not different from posting this in a PDF paper or in a normal topic ! but maybe a change is good. :)

I will post a method I once used to crack an application, It was over 10 Mbytes in size and I didn't want to create a 10 Mbytes patch for

modifying only 10 bytes or less !

What made things even worse was ASLR "Address space layout randomization" in modern operating systems and the protection which was used

on the target, so there was a need to unpack the target then modify a small number of bytes using a hex editor.

so this technique is a special case and I can't claim it's useful as a general solution, the most important point was that I modified the target memory

on a random moment, this means I didn't break on the target's OEP, some applications require that you modify the memory before the application

starts initializing its licensing mechanism, so in my case the bytes that I modified weren't related to the application's license which is usually checked on

startup, so keep this in mind before using this in your tests.


I will leave you with the commented source code in C# :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;


namespace TargetLoader
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {

            // Loader should be launched from the same directory of your target !

            // Create a new process object to launch the target
            Process process = new Process();

            // Configure the process using the StartInfo properties.
            process.StartInfo.FileName = "myTarget.exe";
            process.StartInfo.WindowStyle = ProcessWindowStyle.Maximized;

            // Start the target normally
            process.Start();

            // Unleash your dog !
            // This will return when the memory is modified successfully.
            SND(process.Id);

            // Waits here for the process to exit. << Optional
            process.WaitForExit();// 

        }


        // Windows API needed to open a process and modify its memory

        [DllImport("kernel32.dll")]
        public static extern IntPtr OpenProcess(uint ProcessAccessFlags, bool bInheritHandle, int dwProcessId);

        [DllImport("kernel32.dll")]
        public static extern bool ReadProcessMemory(int hProcess,
          Int64 lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool WriteProcessMemory(int hProcess, Int64 lpBaseAddress,
          byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesWritten);

        // Constants needed for the APIs
        public const UInt32 All = 0x001F0FFF;
        public const UInt32 VirtualMemoryRead = 0x00000010;
        public const UInt32 VirtualMemoryWrite = 0x00000020;
        public const UInt32 VirtualMemoryOperation = 0x00000008;



        public static void SND(int ProcessID)
        {

            // Find the Target Process !
            while (true)
            {

                //Open the process by its ID
                IntPtr processHandle = OpenProcess(All, false, ProcessID);

                // Is it working ?
                if (processHandle != IntPtr.Zero)
                {

                    // Number of read bytes
                    int bytesRead = 0;

                    // Array of bytes holding the original bytes, needed for a mem check although not necessary !
                    byte[] bufferOriginal = new byte[3];

                    // Read the original bytes from memory into the array, we are using RVA here !
                    ReadProcessMemory((int)processHandle, 0x28000024A, bufferOriginal, bufferOriginal.Length, ref bytesRead);

                    // Simple check to make sure we are patching the right bytes !
                    if ((bufferOriginal[0] == 0x33) && (bufferOriginal[1] == 0x34) && (bufferOriginal[2] == 0x35))
                    {

                        int bytesWritten = 0;
                        // The bytes which will modify the application !
                        byte[] bufferNew = new byte[3] { 0x77, 0x78, 0x90 };
                        // Update memory
                        WriteProcessMemory((int)processHandle, 0x28000024A, bufferNew, bufferNew.Length, ref bytesWritten);
                        // Break out of this infinite loop
                        break;
                    }

                    // If we can't find our original bytes then 
                    // Let's wait for 250 ms until our target is unpacked or whatever !
                    System.Threading.Thread.Sleep(250);

                }


            }

        }

    }
}

Source code is included here : Attached File  Program.rar (1.42KB)
downloads: 88

  • 1



So you are basically avoiding the need for retrieving BaseImage because you use ReadProcessMemory/WriteProcessMemory where you don't need the exact VA, just the RVA.

    • 1
  • Report

you are right, I could use the RVA and calculate the right offset later.

 

I should have used the RVA as you said.

 

Just an explanatory example :)

    • 0
  • Report

Either way, looks sexy!

    • 0
  • Report

July 2019

S M T W T F S
 123456
78910111213
1415161718 19 20
21222324252627
28293031   

Recent Comments

Latest Visitors

  • Photo
    johnybo
    11 Jul 2019 - 09:58
  • Photo
    Eddy420CZ
    01 May 2019 - 12:14
  • Photo
    lynx550
    27 Feb 2019 - 10:34
  • Photo
    Fl380
    11 Jan 2019 - 22:15
  • Photo
    Washi
    28 Sep 2018 - 15:51

Categories

MyBlogLog