I'm wanting create a dll injector in Java ( and only in Java ) for educational proporses for myself and found a basic example in a website especialized in online game.
The autor only said that was made using JNA interface.
So, i'm studyng this piece of code and trying compile with success using NetBeans IDE and JNA, but seem that JNA interface that i have here ( 4.2.2 ) not have all methods and functions used on piece of code left by autor.
Are they:
GetProcAddress
VirtualAllocEx
VirtualFreeEx
So, i'm wanting some help here if possible, for try solved this trouble of missing of methods in JNA.
I had fixed big part these erros but still missing some methods in JNA like i will show following point to point with comments.
package inject;
//////////////////// JNA-4.2.2 /////////////////////
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.Tlhelp32;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinDef.HMODULE;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.W32APIOptions;
import java.io.File;
//////////////////////////////////////////////////
// Extracted from: https://github.com/warmuuh/AndroidCtx/tree/master/HotContext/src/luz/winapi
import inject.luz.winapi.constants.DwDesiredAccess;
import inject.luz.winapi.tools.Advapi32Tools;
import inject.luz.winapi.tools.Kernel32Tools;
import luz.winapi.api.exception.Kernel32Exception;
//////////////////////////////////////////////////////////////////////////////////////////////
public class Inject {
private static int GetPid(String proc){
int id = 0;
Kernel32 kernel32 = (Kernel32) Native.loadLibrary(Kernel32.class, W32APIOptions.UNICODE_OPTIONS);
Tlhelp32.PROCESSENTRY32.ByReference processEntry = new Tlhelp32.PROCESSENTRY32.ByReference();
WinNT.HANDLE snapshot = kernel32.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPPROCESS, new WinDef.DWORD(0));
try {
while (kernel32.Process32Next(snapshot, processEntry)) {
if (Native.toString(processEntry.szExeFile).equalsIgnoreCase(proc)) {
id = processEntry.th32ProcessID.intValue();
}
}
}
finally {
kernel32.CloseHandle(snapshot);
}
return id;
}
private static String findProcessByPID(int pid){
String name = "";
Kernel32 kernel32 = (Kernel32) Native.loadLibrary(Kernel32.class, W32APIOptions.UNICODE_OPTIONS);
Tlhelp32.PROCESSENTRY32.ByReference processEntry = new Tlhelp32.PROCESSENTRY32.ByReference();
WinNT.HANDLE snapshot = kernel32.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPPROCESS, new WinDef.DWORD(0));
try {
while (kernel32.Process32Next(snapshot, processEntry)) {
if (pid == processEntry.th32ProcessID.intValue()) {
name = processEntry.szExeFile.toString();
}
}
}
finally {
kernel32.CloseHandle(snapshot);
}
return name;
}
public static void inject(File dll, Integer pId) throws Kernel32Exception {
if(null == dll || !dll.exists() || !dll.isFile() || !dll.getName().endsWith(".dll"))
return;
String p = findProcessByPID(pId);
if(null == p) return;
Kernel32 kernel = Kernel32.INSTANCE;
HMODULE kernel32Pointer = kernel.GetModuleHandle("Kernel32");
// Cannot find "GetProcAddress"
Pointer loadLibraryAddress = kernel.GetProcAddress(kernel32Pointer, "LoadLibraryA");
HANDLE process = null;
DwDesiredAccess access = new DwDesiredAccess();
access.setPROCESS_ALL_ACCESS();
try {
Advapi32Tools.getInstance().enableDebugPrivilege(Kernel32Tools.getInstance().GetCurrentProcess());
} catch (Exception e) {
}
// Incompatible types "Pointer" and "HANDLE"
process = Kernel32Tools.getInstance().OpenProcess(access, false, pId);
String path = dll.getPath() + '\0';
byte[] bytes = path.getBytes();
int pathLength = bytes.length;
// Cannot find "VirtualAllocEx"
Pointer memoryDllPath = kernel.VirtualAllocEx(process, null, pathLength, Kernel32Tools.MEM_COMMIT, Kernel32Tools.PAGE_READWRITE);
Memory dllPathContent = new Memory(pathLength);
for(int i=0;i<pathLength;i++)
dllPathContent.setByte(i, bytes[i]);
IntByReference writeResult = new IntByReference();
boolean successWritting = kernel.WriteProcessMemory(process, memoryDllPath, dllPathContent, pathLength, writeResult);
if(!successWritting) {
kernel.CloseHandle(process);
return;
}
IntByReference threadId = new IntByReference();
// Pointer cannot be converted to "FOREIGN_THREAD_START_ROUTINE"
Pointer thread = kernel.CreateRemoteThread(process, null, 0, loadLibraryAddress, memoryDllPath, 0, threadId);
boolean res = false;
// Incompatible types "Pointer" and "HANDLE" //Cannot find "WAIT_TIMEOUT"
res = kernel.WaitForSingleObject(thread, Integer.MAX_VALUE) != Kernel32Tools.WAIT_TIMEOUT;
// Cannot find "VirtualFreeEx" method // Cannot find "MEM_RELEASE"
kernel.VirtualFreeEx(process, memoryDllPath, pathLength, Kernel32Tools.MEM_RELEASE);
kernel.CloseHandle(process);
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
System.out.println(GetPid("notepad.exe"));
}
}
Thank in advance by any suggestion or help :-)
JNA missing methods? It ain't so!
You just need to extend the library and add your own (and, ideally, also contribute the "missing" methods back to the JNA library so others can benefit.
Here is an example of how someone has mapped GetProcAddress.
Someone has mapped VirtualAllocEx here (although they should properly have extended Kernel32 rather than copied it entirely and edited portions)
I couldn't find an example of VirtualFreeEx within the same 15 seconds I found the others... doesn't mean it's not out there but after writing the others you shouldn't have much trouble writing it as well.
Related
I have tried using both
Toolkit.getDefaultToolkit().beep(); and
System.out.println("\007");
and neither are actually playing a sound. I tried running the code in my IDE (CodeRunner 2) and in Terminal to see if it made a difference, which it didn't.
If anyone know another way to do this or why it isn't working, please let me know
Thanks!
Or you might try to use it with JNA-Library:
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.Native;
import com.sun.jna.Library;
interface JnaTests extends Library {
public boolean Beep(int FREQUENCY , int DURATION );
static Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
static void startBeep() throws InterruptedException {
kernel32.Beep(1200, (5000));
Thread.sleep(50);
}
}
package com.sun.jna.platform;
import com.sun.jna.Library;
public class win32 {
private static class MSG implements User32 {
public MSG() {
}
}
public interface Kernel32 extends Library { // ... (lines deleted for clarity) ...
boolean Beep(int frequency, int duration);
//int GetLogicalDrives(); // ... (lines deleted for clarity) ... }
}
public interface User32 extends Library { // ... (lines deleted for clarity) ...
// ... (lines deleted for clarity) ... }
}
}
Perhaps you could use the midi class too:
Sequencer sequencer = MidiSystem.getSequencer();
sequencer.open();
Sequence sequence = new Sequence(Sequence.PPQ,4);
Track track = sequence.createTrack();
ShortMessage a = new ShortMessage();
a.setMessage(144,9,56,100);
MidiEvent event = new MidiEvent(a, 1);
track.add(event);
sequencer.setSequence(sequence);
sequencer.start();
Thread.sleep(500);
sequencer.close();
I think you are looking for Runtime#exec(String):
Runtime.getRuntime().exec(cmd);
This should allow you to get an instance of the current environment in which you can issue such commands.
I'm writing an implementation of setsockopt under JNA. Java itself supports setsockopt, but it doesn't support all the platform specific socket options. For instance, it doesn't support [TCP_KEEPIDLE][2] under Linux. Clearly, many of these options are not very portable, and using JNA is a route to poor portability; I am aware of this. Please don't bother to tell me the idea is deeply horrible.
What I'd like to do, however, is make my code a little more reuseable than something that just works under Linux. I'd like it to work (as far as is possible) on several target platforms. If the socket option is not available, it can throw an exception.
My challenge is this. The JNA works fine, but the values of the socket options are different across platforms. For instance, SO_RCVBUF is 0x1002 under OS-X and 8 under Linux (I realise SO_RCVBUF is controllable by the normal Java setSockOpt - it's an example that's easy to test with lsof). SO_DONTROUTE is 5 under Linux, and 0x0010 under OS-X (and that isn't controllable via Java setSockOpt).
So what I'd like it to do is to take an enum value representing the socket option (SO_SNDBUF, SO_RCVBUF or whatever), and look that up in a platform dependent map, so I get 0x1002 / 0x010 under OS-X and 8 / 5 under Linux.
That's easy enough, but how do I tell what the platform is under JNA so I know which map to use? JNA must somehow have a sense of its own platform, or it would not (I presume) know how to call the native libraries.
package sockettest;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.Socket;
import com.sun.jna.LastErrorException;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
public class JNASockOpt {
private static Field fdField;
static {
Native.register("c");
try {
fdField = FileDescriptor.class.getDeclaredField("fd");
fdField.setAccessible(true);
} catch (Exception ex) {
fdField = null;
}
}
public static int getInputFd(Socket s) {
try {
FileInputStream in = (FileInputStream)s.getInputStream();
FileDescriptor fd = in.getFD();
return fdField.getInt(fd);
} catch (Exception e) { }
return -1;
}
public static int getOutputFd(Socket s) {
try {
FileOutputStream in = (FileOutputStream)s.getOutputStream();
FileDescriptor fd = in.getFD();
return fdField.getInt(fd);
} catch (Exception e) { }
return -1;
}
public static int getFd(Socket s) {
int fd = getInputFd(s);
if (fd != -1)
return fd;
return getOutputFd(s);
}
// The list of SOL_ and SO_ options is platform dependent
public static final int SOL_SOCKET = 0xffff; // that's under OS-X, but it's 1 under Linux
public static final int SO_RCVBUF = 0x1002; // that's under OS-X, but it's 8 under Linux
public static final int SO_DONTROUTE = 0x0010; // that's under OS-X, but it's 5 under Linux
private static native int setsockopt(int fd, int level, int option_name, Pointer option_value, int option_len) throws LastErrorException;
public static void setSockOpt (Socket socket, int level, int option_name, int option_value) throws IOException {
if (socket == null)
throw new IOException("Null socket");
int fd = getFd(socket);
if (fd == -1)
throw new IOException("Bad socket FD");
IntByReference val = new IntByReference(option_value);
try {
setsockopt(fd, level, option_name, val.getPointer(), 4);
} catch (LastErrorException ex) {
throw new IOException("setsockopt: " + strerror(ex.getErrorCode()));
}
}
public static native String strerror(int errnum);
private JNASockOpt() {
}
}
The class com.sun.jna.Platform provided by JNA is used by JNA itself and has functions for querying the OS family and CPU architecture.
There are static methods for isMac() and isLinux().
jnaplatform does this by string parsing System.getProperty("os.name");, which seems pretty horrible to me, but if jnaplatform does it, I guess that should be good enough for me.
Results (i.e. how I used the above idea to solve the issue in the question) at https://github.com/abligh/jnasockopt - specifically https://github.com/abligh/jnasockopt/blob/master/src/org/jnasockopt/JNASockOptionDetails.java
Is it possible to determine, what client libs have been loaded prior to a component?
We are running multiple site backed by different Javascript frameworks. In order to run a single component across the board, it's not sufficient to just use
<cq:includeClientLib categories="blah"/>
We need to identify the respective framework (i.e. AngularJS, Vanilla, jQuery, blah) in order to facilitate the integration.
We are looking for a decent server side solution.
I haven't actually done this, but it would presumably be possible if you are buffering your output to clone the JspWriter buffer or examine it to see what it already contains. That sounds ugly to me, though. But this is decompiled code for how the cq:includeClientLib tag adds libraries to the output, which may show you how you can read back what was previously written:
package com.adobe.granite.ui.tags;
import com.day.cq.widget.HtmlLibraryManager;
import java.io.IOException;
import javax.servlet.ServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.TagSupport;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.scripting.SlingBindings;
import org.apache.sling.scripting.jsp.util.TagUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class IncludeClientLibraryTag extends TagSupport {
private static final long serialVersionUID = -3068291967085012331L;
private static final Logger log = LoggerFactory.getLogger(IncludeClientLibraryTag.class);
private String categories;
private String js;
private String css;
private String theme;
private Boolean themed;
public IncludeClientLibraryTag() {
}
public void setPageContext(PageContext pageContext) {
super.setPageContext(pageContext);
this.categories = null;
this.js = null;
this.css = null;
this.theme = null;
this.themed = null;
}
public void setCategories(String categories) {
this.categories = categories;
}
public void setJs(String js) {
this.js = js;
}
public void setCss(String css) {
this.css = css;
}
public void setTheme(String theme) {
this.theme = theme;
}
public void setThemed(boolean themed) {
this.themed = Boolean.valueOf(themed);
}
public int doEndTag() throws JspException {
SlingHttpServletRequest request = TagUtil.getRequest(this.pageContext);
HtmlLibraryManager libManager = this.getHtmlLibraryManager(request);
if(libManager == null) {
log.warn("<ui:includeClientLib>: Could not retrieve HtmlLibraryManager service, skipping inclusion.");
return 6;
} else {
JspWriter out = this.pageContext.getOut();
try {
if(this.categories != null) {
libManager.writeIncludes(request, out, toArray(this.categories));
} else if(this.theme != null) {
libManager.writeThemeInclude(request, out, toArray(this.theme));
} else if(this.js != null) {
if(this.themed != null) {
libManager.writeJsInclude(request, out, this.themed.booleanValue(), toArray(this.js));
} else {
libManager.writeJsInclude(request, out, toArray(this.js));
}
} else if(this.css != null) {
if(this.themed != null) {
libManager.writeCssInclude(request, out, this.themed.booleanValue(), toArray(this.css));
} else {
libManager.writeCssInclude(request, out, toArray(this.css));
}
}
return 6;
} catch (IOException var6) {
String libs = this.categories != null?"categories: " + this.categories:(this.theme != null?"theme: " + this.theme:(this.js != null?"js: " + this.js:(this.css != null?"css: " + this.css:"")));
throw new JspException("Could not include client library: " + libs, var6);
}
}
}
private HtmlLibraryManager getHtmlLibraryManager(ServletRequest request) {
SlingBindings bindings = (SlingBindings)request.getAttribute(SlingBindings.class.getName());
return (HtmlLibraryManager)bindings.getSling().getService(HtmlLibraryManager.class);
}
private static String[] toArray(String commaSeparatedList) {
if(commaSeparatedList == null) {
return new String[0];
} else {
String[] split = commaSeparatedList.split(",");
for(int i = 0; i < split.length; ++i) {
split[i] = split[i].trim();
}
return split;
}
}
}
I think the best solution may be to use the client library dependencies or embed attributes in your library, though, or let the client-side JavaScript test if a library is present (ex. test if the jQuery object is undefined) and then take appropriate action. In other words, let the client side determine the final rendering based on what libraries exist on in the client. It sounds like this may not be possible for your situation, though.
dependencies: This is a list of other client library categories on
which this library folder depends. For example, given two
cq:ClientLibraryFolder nodes F and G, if a file in F requires another
file in G in order to function properly, then at least one of the
categories of G should be among the dependencies of F.
embed: Used to > embed code from other libraries. If node F embeds nodes G and H, the
resulting HTML will be a concetration of content from nodes G and H.
I'm trying to create a phonegap plugin for an android device, sadly my Java is terrible.
I have a simple helloworld project i'm working in to try and get this going.
I've created a plugin which loads fine and works ( just a simple return string example )
From this i then have tried to add my native library code.
public class Medida extends CordovaPlugin
{
static {
System.loadLibrary("finger");
}
public native static int SFM_Init(byte[] dev);
The error message i keep encountering is:
10-28 15:23:03.207: W/dalvikvm(11618): No implementation found for native Lorg/apache/cordova/plugin/Medida;.SFM_Init ([B)I
Now - I'm taking the libfinger.so file from a full JAVA android project and trying to wrap it into a phonegap plugin (why? Because i can code phonegap, but no java).
The files are all been placed in the correct locations
the libfinger.so file is in the libs/ folder
So my question is - what else do i need to add-in or do to get the JAVA plugin to work with the libfinger.so - so i can call all the clases etc..
Thanks for looking - spents days trying to find out, but there is not much info on calling loadlibrary for plugins which i understand.
John
Main java class
package org.apache.cordova.plugin;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
public class Medida extends CordovaPlugin{
static {
System.loadLibrary("finger");
}
public native static int SFM_Init(byte[] dev);
static final String LOG_TAG = "Medida.Java: ";
int fd = 0;
String retval = null;
int[] nQuality = {0};
int[] nBufferSize = {0};
private final String retSuccess = "OK";
public static final int REFRESH = 1;
public static final int ERROR = 0;
private Thread thread = null;
private int peripheral_fd = 1;
#Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
if (action.equals("dave")) {
String message = args.getString(0);
this.dave("Medida CALLING DAVE " + message, callbackContext);
return true;
}
else if (action.equals("scanfinger_getID")){
this.scanfinger_getID( args, callbackContext);
return true;
}
return false;
}
private void dave(String message, CallbackContext callbackContext) {
if (message != null && message.length() > 0) {
callbackContext.success(" --- Medida FROM DAVE: " + message);
} else {
callbackContext.error("Expected one non-empty string argument.");
}
}
private void scanfinger_getID(JSONArray args, CallbackContext callbackContext) throws JSONException {
String message = args.getString(0);
JSONObject object = new JSONObject(message);
String id = object.getString("id");
String dev = "/dev/ttySAC3";
byte[] devName = dev.getBytes();
fd = SFM_Init(devName);
callbackContext.success("Got to scanfinger_getID: " + id);
}
}
Try to define the method as a class method (taken from here):
public class Medida extends CordovaPlugin {
static {
System.loadLibrary("finger");
}
public native int SFM_Init(byte[] dev);
}
EDIT
From the error it seems that there is no method called SFM_Init in the native library, try to list the exported methods and see the exact definition: How do I list the symbols in a .so file
The is actually related to the question How can I add row numbers for rows in PIG or HIVE?
The 3rd answer provided by srini works fine, but I have trouble to access the data after the udf.
The udf provided by srini is following
import java.io.IOException;
import java.util.Iterator;
import org.apache.pig.EvalFunc;
import org.apache.pig.backend.executionengine.ExecException;
import org.apache.pig.data.BagFactory;
import org.apache.pig.data.DataBag;
import org.apache.pig.data.Tuple;
import org.apache.pig.data.TupleFactory;
import org.apache.pig.impl.logicalLayer.schema.Schema;
import org.apache.pig.data.DataType;
public class RowCounter extends EvalFunc<DataBag> {
TupleFactory mTupleFactory = TupleFactory.getInstance();
BagFactory mBagFactory = BagFactory.getInstance();
public DataBag exec(Tuple input) throws IOException {
try {
DataBag output = mBagFactory.newDefaultBag();
DataBag bg = (DataBag)input.get(0);
Iterator it = bg.iterator();
Integer count = new Integer(1);
while(it.hasNext())
{ Tuple t = (Tuple)it.next();
t.append(count);
output.add(t);
count = count + 1;
}
return output;
} catch (ExecException ee) {
// error handling goes here
throw ee;
}
}
public Schema outputSchema(Schema input) {
try{
Schema bagSchema = new Schema();
bagSchema.add(new Schema.FieldSchema("RowCounter", DataType.BAG));
return new Schema(new Schema.FieldSchema(getSchemaName(this.getClass().getName().toLowerCase(), input),
bagSchema, DataType.BAG));
}catch (Exception e){
return null;
}
}
}
I wrote a simple test pig script as following
A = load 'input.txt' using PigStorage(' ') as (name:chararray, age:int);
/*
--A: {name: chararray,age: int}
(amy,56)
(bob,1)
(bob,9)
(amy,34)
(bob,20)
(amy,78)
*/
B = group A by name;
C = foreach B {
orderedGroup = order A by age;
generate myudfs.RowCounter(orderedGroup) as t;
}
/*
--C: {t: {(RowCounter: {})}}
({(amy,34,1),(amy,56,2),(amy,78,3)})
({(bob,1,1),(bob,9,2),(bob,20,3)})
*/
D = foreach C generate FLATTEN(t);
/*
D: {t::RowCounter: {}}
(amy,34,1)
(amy,56,2)
(amy,78,3)
(bob,1,1)
(bob,9,2)
(bob,20,3)
*/
The problem is how to use D in later operation. I tried multiple ways, but always got the following error
ava.lang.ClassCastException: java.lang.String cannot be cast to org.apache.pig.data.DataBag
at org.apache.pig.backend.hadoop.executionengine.physicalLayer.expressionOperators.POProject.processInputBag(POProject.java:575)
at org.apache.pig.backend.hadoop.executionengine.physicalLayer.expressionOperators.POProject.getNext(POProject.java:248)
at org.apache.pig.backend.hadoop.executionengine.physicalLayer.PhysicalOperator.getNext(PhysicalOperator.java:316)
at org.apache.pig.backend.hadoop.executionengine.physicalLayer.relationalOperators.POForEach.processPlan(POForEach.java:332)
at org.apache.pig.backend.hadoop.executionengine.physicalLayer.relationalOperators.POForEach.getNext(POForEach.java:284)
at org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.PigGenericMapReduce$Reduce.runPipeline(PigGenericMapReduce.java:459)
at org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.PigGenericMapReduce$Reduce.processOnePackageOutput(PigGenericMapReduce.java:427)
at org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.PigGenericMapReduce$Reduce.reduce(PigGenericMapReduce.java:407)
at org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.PigGenericMapReduce$Reduce.reduce(PigGenericMapReduce.java:261)
at org.apache.hadoop.mapreduce.Reducer.run(Reducer.java:176)
at org.apache.hadoop.mapred.ReduceTask.runNewReducer(ReduceTask.java:572)
at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:414)
at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:256)
My guess is that because we don't have the schema for the tuple inside the bag. if this is the reason, how should I modify the udf?
ok, I found the solution by adding the outputSchema as following
public Schema outputSchema(Schema input) {
try{
Schema.FieldSchema counter = new Schema.FieldSchema("counter", DataType.INTEGER);
Schema tupleSchema = new Schema(input.getField(0).schema.getField(0).schema.getFields());
tupleSchema.add(counter);
Schema.FieldSchema tupleFs;
tupleFs = new Schema.FieldSchema("with_counter", tupleSchema, DataType.TUPLE);
Schema bagSchema = new Schema(tupleFs);
return new Schema(new Schema.FieldSchema("row_counter",
bagSchema, DataType.BAG));
}catch (Exception e){
return null;
}
}
}
Thanks.