Saturday, 31 August 2013

Creating a Fork of Jni4Net,dealing with ‘Attempted to read or write protected memory’ problem and what I had to do to make it work with ZAP

An O2 user was having some issues with the Jni4Net scripts and I think the root cause is because the current O2 Scripts uses the jni4net.n-0.8.6.0.dll which is the version currently available for download
image

TLDR: The code of the patched version is here the compiled binaries are here

NOTE: THIS VERSION IS CURRENTLY published as DRAFT since I'm on the Algarve (i.e. the beach is waiting) and don't have time to proof read the text below (which is posted how I wrote it at the time)

The problem is that with the 0.8.6 version we would get an ‘Attempted to read or write protected memory’ error when trying to connect to an existing Java process we injected O2 into (see note below for more details)

If I remember correctly (when I was able to make it work before, see Using Jni4Net part 1, part 2,  part 3 and part 4) the solution is to use the latest version of Jni4Net, which is not available for direct download, but its code it at: http://jni4net.googlecode.com/svn jni4Net

Using the git svn clone -s http://jni4net.googlecode.com/svn jni4Net command, I created a local clone of the SVN repo:
image
After getting the compilation and generation process right (see below), I had this folder:
image
I then used these scripts (see this gist for code) to:
1) start ZAP and inject O2 into the new process:
image
2) hook VisualStudio to that process (assumes there is only one java.exe process)
image
3) create bridge and output java properties (inside the ZAP REPL)
image
4) Executed PoC - Jni4Net - Classes, Methods, Fields in target.h2 script (inside ZAP process)
image
which listed all loaded java classes (and its decompiled code):
image

To make this work (and deal with the ‘Attempted to read or write protected memory’ prob) I had to copy the jni4net.j-0.8.7.0.jar to the ZAP default class path and manually skip a bit of code when connected to VisualStudio
image

NOTE XYZ)  How I got the whole compilation process to work
I started by opening the jni4net.sln file in VS 2010.
But on first compile I had this error:
image
which was created by the missing selvin.exportdllattribute-0.2.6.0.dll
image
which looks like should be here:
image
let’s take a look at the v0-8-generics branch
image
but it is also not there, so I just downloaded it from:
We can find the file on the tools
image
… and saved it to:
image
… updated the references
image
Now the code compiles, but we get this error:
image
which is caused by this post build command:
image
and is resolved by downloading this file:
image
into this folder:
image
I was able to get it to compile by changing the selvin.exportdll-0.2.6.0.exe to selvin.exportdll-0.2.5.0.exe (couldn’t find the 0.2.6.0 version)
image
Next there was a bunch of NUnit errors, which were resolved using
image
and now we have a clean compilation (with only a bunch of warnings)
image
But, they all fail to execute:
image
Which was a good sign that I should look for a readme.txt, which I found in the repo root:
image
Running loadTools.cmd:
image
… downloads the missing files into the lib folder:
image
Since we now have the 0.2.6.0 versions I updated back the VS solution (and removed the nUnit package from Nuget)
Then I executed
image
and
image
this took a while, and although most looked ok:
image
it looks like the last one failed:
image
But the required files seemed to have been created:
image
And the Unit tests now pass:
image
I still don’t like the fact that we have that build error, so I track it to the missing NUnit installation. So I downloaded and installed the expected one
image
but since I’m on a x64 VM and the path is hard-coded in the Maven script, I had to copy the installed nunit files to the expected folder:
image
humm, maybe that wasn’t such a good idea:
image
I think the problem could be caused by the fact that I’m currently using an x64 JDK:
image
So let’s try with a x86 (32bit) version of the JDK
image
now the tests expect to find Nunit in the (x86) folder:
image
which should be fixed by renaming the NUnit-2.5.8 folder to the expected value:
image
And finally we have a successful complete build:
image
with all created files placed inside the target folder:
image


NOTE XYZ) replicating the original ‘Attempted to read or write protected memory’ error
get this error when trying to connect to a java process like ZAP:
image
which we can inject O2 into
image
And if I try to execute the PoC - Jni4Net - List JavaProperties.h2 process, I get an unmanaged error (which is always a worse case scenario in the .NET Interop world)
image
As the (simpler script shows), the error happens on the  CreateJVM invocation
image
My next step was to create a local build of Jni4Net (which you saw on the preview note) and to use it to attach into an existing running ZAP with an O2 REPL injected.
Here is the moment when I have VisualStudio hooked, the script compiled (in the ZAP REPL), the jni4net dll loaded (with Symbols) in VisualStudio and a breakpoint on the CreateJVM method:
image
Here is where I think the problem exists:
image
the args object (created via JNI) seems to be empty.
It is then assigned to the value of the Jni4Net class path string
image
The args object is used here:
image
And inside that method, if I let args to be used, we will get the ‘Attempted to read or write protected memory’ error
image
but, if I change the execution path (manually) and set it to the line below (where no args is passed)
image
Then the execution will be ok (note that the path with the &initArgs would had thrown an ‘Attempted to read or write protected memory’  by now):
image
The only problem with this approach (which is basically not adding the classpath clue to the current JVM) is that unless we manually add the jni4net jar to the target app, we will get an exception here:
image
i.e. br.handle would be 0 (meaning that the net.sf.jnin4net.Bridge class could not be found)
Note AAA) Fixing the issue
I added the Patch_IgnoreArgsInAttach property
image
Which is then used here (to allow the selection of the path that works)
image
I also changed the assembly name (so it is easy to track its use):
image
After the compilation I copied it to the main target folder:
image
To test it , I used the script
image
to start ZAP with a REPL, where I could execute OK:
image
Final step is to create a zip of the bin folder
image
Put it on a public available location like DropBox
Update the installer API to use that version:
image
Update the API_Jni4Net.cs to use the jni4net.n-0.8.7.0_Patched.dll assembly (as seen below on first compile the referenced will be downloaded)
image
once the compilation works:
image
Running Jni4Net works locally
image
And so does on ‘injected into’ java processes:
image
Finally I can add a remote to the local repo:
image
push it
image
And confirm that the commits I did locally (with the patch)
image
where pushed successfully:
image

NOTE ABC) Starting ZAP programmatically
Here is a script that starts (and downloads on first run) the latest version of ZAP (return value is the new ZAP process, and ZAP’s console out are being captured in the O2’s LogViewer):
image
Here is the contents of the API_Zap.cs file (consumed above):
image

Note #2) Setting default folders
In this case I also had to update the location of the temp and O2.Platform.Scripts folder (usually not needed)
image