Created
November 9, 2011 09:37
-
-
Save anonymous/1350968 to your computer and use it in GitHub Desktop.
NPAPI simple example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <dlfcn.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <gtk/gtk.h> | |
#include <gdk/gdkx.h> | |
#include "npapi.h" | |
#include "npfunctions.h" | |
#ifdef __i386__ | |
#define FLASH_PLUGIN_SO "./flash/libflashplayer32.so" | |
#else | |
#define FLASH_PLUGIN_SO "./flash/libflashplayer64.so" | |
#endif | |
#define WINDOW_XSIZE 800 | |
#define WINDOW_YSIZE 600 | |
void *flash_plugin_handle; | |
NPNetscapeFuncs browserFuncs; | |
NPPluginFuncs pluginFuncs; | |
GtkWidget *main_window; | |
char* URL; | |
NPStream * stream; | |
const char * uagent = "Axt/1.0"; | |
NPError (*iNP_Initialize)(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs); | |
NPError (*iNP_Shutdown)(); | |
char* (*iNP_GetMIMEDescription)(); | |
void* loadFlashPluginSo() { | |
void *handle; | |
handle = dlopen(FLASH_PLUGIN_SO, RTLD_LAZY); | |
if(!handle) { | |
fprintf(stderr, "[-] error loading libflasplayer.so: %s\n", dlerror()); | |
exit(1); | |
} | |
puts("[+] loaded libflashplayer.so"); | |
return handle; | |
} | |
void* loadSymbol(void *handle, const char *name) { | |
char *error; | |
void *ret; | |
ret = dlsym(handle, name); | |
if((error = dlerror()) != NULL) { | |
fprintf(stderr, "[-] error loading symbol %s: %s\n", name, error); | |
exit(1); | |
} else { | |
printf("[+] loaded symbol %s, address: %p\n", name, ret); | |
} | |
return ret; | |
} | |
void loadNPEntryPoints(void *handle) { | |
iNP_Initialize=loadSymbol(handle, "NP_Initialize"); | |
iNP_Shutdown=loadSymbol(handle, "NP_Shutdown"); | |
iNP_GetMIMEDescription = loadSymbol(handle,"NP_GetMIMEDescription"); | |
} | |
void printPluginEntrypoints(NPPluginFuncs* pFuncs) { | |
printf("[*] NPP struct:\n"); | |
printf("\t- NPP_size: %8d\n",pFuncs->size); | |
printf("\t- NPP_version: %8d\n",pFuncs->version); | |
printf("\t- NPP_NewProcPtr: %p\n", pFuncs->newp); | |
printf("\t- NPP_DestroyProcPtr: %p\n", pFuncs->destroy); | |
printf("\t- NPP_SetWindowProcPtr: %p\n", pFuncs->setwindow); | |
printf("\t- NPP_NewStreamProcPtr: %p\n", pFuncs->newstream); | |
printf("\t- NPP_DestroyStreamProcPtr: %p\n", pFuncs->destroystream); | |
printf("\t- NPP_StreamAsFileProcPtr: %p\n", pFuncs->asfile); | |
printf("\t- NPP_WriteReadyProcPtr: %p\n", pFuncs->writeready); | |
printf("\t- NPP_WriteProcPtr: %p\n", pFuncs->write); | |
printf("\t- NPP_PrintProcPtr: %p\n", pFuncs->print); | |
printf("\t- NPP_HandleEventProcPtr: %p\n", pFuncs->event); | |
printf("\t- NPP_URLNotifyProcPtr: %p\n", pFuncs->urlnotify); | |
printf("\t- javaClass: %p\n", pFuncs->javaClass); | |
printf("\t- NPP_GetValueProcPtr: %p\n", pFuncs->getvalue); | |
printf("\t- NPP_SetValueProcPtr: %p\n", pFuncs->setvalue); | |
} | |
NPError NPN_GetValueProc(NPP instance, NPNVariable variable, void *ret_value) { | |
printf("[D] NPN_GetValueProc instance:%p, variable:%d, abi_mask:%d\n", instance, variable, 0); | |
if(variable == 14) | |
*((int*)ret_value)=1; | |
else if(variable == 268435469) | |
*((int*)ret_value)=2; | |
else if(variable == 15) | |
*((int*)ret_value)=1;//TODO | |
else | |
*((int*)ret_value)=0; | |
return NPERR_NO_ERROR; | |
} | |
const char* NPN_UserAgentProc(NPP instance) { | |
printf("[D] NPN_UserAgentProc instance:%p\n", instance); | |
return uagent; | |
} | |
NPError NPN_GetURLProc(NPP instance, const char* url, const char* window) { | |
printf("[D] NPN_GetURLProcPtr:%p, url: %s, window: %s\n", instance, url, window); | |
return NPERR_NO_ERROR; | |
} | |
NPIdentifier NPN_GetStringIdentifierProc(const NPUTF8* name) { | |
return (NPIdentifier)0x41424344; | |
} | |
static | |
gboolean plug_removed_cb (GtkWidget *widget, gpointer data) { | |
printf("[!] plug_removed_cb\n"); | |
return TRUE; | |
} | |
static void | |
socket_unrealize_cb(GtkWidget *widget, gpointer data) { | |
printf("[!] socket_unrealize_cb\n"); | |
} | |
static NPWindow * | |
npwindow_construct (GtkWidget *widget) { | |
NPWindow *npwindow; | |
NPSetWindowCallbackStruct *ws_info = NULL; | |
GdkWindow *parent_win = widget->window; | |
GtkWidget *socketWidget = gtk_socket_new(); | |
gtk_widget_set_parent_window(socketWidget, parent_win); | |
g_signal_connect(socketWidget, "plug_removed", G_CALLBACK(plug_removed_cb), NULL); | |
g_signal_connect(socketWidget, "unrealize", G_CALLBACK(socket_unrealize_cb), NULL); | |
g_signal_connect(socketWidget, "destroy", G_CALLBACK(gtk_widget_destroyed), &socketWidget); | |
gpointer user_data = NULL; | |
gdk_window_get_user_data(parent_win, &user_data); | |
GtkContainer *container = GTK_CONTAINER(user_data); | |
gtk_container_add(container, socketWidget); | |
gtk_widget_realize(socketWidget); | |
GtkAllocation new_allocation; | |
new_allocation.x = 0; | |
new_allocation.y = 0; | |
new_allocation.width = WINDOW_XSIZE; | |
new_allocation.height = WINDOW_YSIZE; | |
gtk_widget_size_allocate(socketWidget, &new_allocation); | |
gtk_widget_show(socketWidget); | |
gdk_flush(); | |
GdkNativeWindow ww = gtk_socket_get_id(GTK_SOCKET(socketWidget)); | |
GdkWindow *w = gdk_window_lookup(ww); | |
npwindow = malloc (sizeof (NPWindow)); | |
npwindow->window = (void*)(unsigned long)ww; | |
npwindow->x = 0; | |
npwindow->y = 0; | |
npwindow->width = WINDOW_XSIZE; | |
npwindow->height = WINDOW_YSIZE; | |
ws_info = malloc(sizeof (NPSetWindowCallbackStruct)); | |
ws_info->type = NP_SETWINDOW; | |
ws_info->display = GDK_WINDOW_XDISPLAY(w); | |
ws_info->colormap = GDK_COLORMAP_XCOLORMAP(gdk_drawable_get_colormap(w)); | |
GdkVisual* gdkVisual = gdk_drawable_get_visual(w); | |
ws_info->visual = GDK_VISUAL_XVISUAL(gdkVisual); | |
ws_info->depth = gdkVisual->depth; | |
npwindow->ws_info = ws_info; | |
npwindow->type = NPWindowTypeWindow; | |
return npwindow; | |
} | |
static NPStream * | |
npstream_construct() { | |
NPStream *stream = malloc(sizeof(NPStream)); | |
stream->url=URL; | |
stream->ndata = 0; | |
stream->end = 99782; | |
stream->lastmodified= 1201822722; | |
stream->notifyData = 0x00000000; | |
stream->headers = malloc(200); | |
return stream; | |
} | |
bool NPN_GetPropertyProc(NPP npp, NPObject *obj, NPIdentifier propertyName, NPVariant *result) { | |
result->type=6; | |
result->value.objectValue= (NPObject*)1; | |
return TRUE; | |
} | |
bool NPN_InvokeProc(NPP npp, NPObject* obj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result) { | |
result->type=5; | |
result->value.stringValue.utf8characters=URL; | |
result->value.stringValue.utf8length=strlen(URL); | |
return TRUE; | |
} | |
void NPN_ReleaseVariantValueProc(NPVariant *variant) { | |
} | |
void NPN_ReleaseObjectProc(NPObject *obj) { | |
} | |
NPObject* NPN_CreateObjectProc(NPP npp, NPClass *aClass) { | |
return (NPObject*)1; | |
} | |
NPObject* NPN_RetainObjectProc(NPObject *obj) { | |
return (NPObject*)1; | |
} | |
NPError NPN_GetURLNotifyProc(NPP instance, const char* url, const char* window, void* notifyData) { | |
printf("[D] NPN_GetURLNotifyProc:%p, url: %s, window: %s\n", instance, url, window); | |
return 0; | |
} | |
void initNPNetscapeFuncs(NPNetscapeFuncs *bFuncs) { | |
int i=0; | |
for(i=1; i<sizeof(*bFuncs)/sizeof(ssize_t); i++) | |
*(((ssize_t*)bFuncs)+i)=i+1000; | |
bFuncs->geturl=NPN_GetURLProc; | |
bFuncs->getvalue=NPN_GetValueProc; | |
bFuncs->uagent=NPN_UserAgentProc; | |
bFuncs->getproperty=NPN_GetPropertyProc; | |
bFuncs->getstringidentifier=NPN_GetStringIdentifierProc; | |
bFuncs->invoke=NPN_InvokeProc; | |
bFuncs->releasevariantvalue=NPN_ReleaseVariantValueProc; | |
bFuncs->releaseobject=NPN_ReleaseObjectProc; | |
bFuncs->createobject=NPN_CreateObjectProc; | |
bFuncs->retainobject=NPN_RetainObjectProc; | |
bFuncs->geturlnotify=NPN_GetURLNotifyProc; | |
bFuncs->size=60; | |
bFuncs->version=20; | |
} | |
static void destroy(GtkWidget *widget, gpointer data) { | |
gtk_main_quit (); | |
} | |
static void checkError(const char* str, NPError err) { | |
if(err == NPERR_NO_ERROR) | |
printf("[+] %s: success\n", str); | |
else | |
printf("[-] %s: failed (%d)\n", str, err); | |
fflush(); | |
} | |
int main(int argc, char **argv) | |
{ | |
if(argc < 2) { | |
printf("[-] Usage: %s <swfuri>\n", argv[0]); | |
exit(-1); | |
} | |
URL = argv[1]; | |
gtk_init (&argc, &argv); | |
main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); | |
gtk_widget_set_usize (main_window, WINDOW_XSIZE, WINDOW_YSIZE); | |
g_signal_connect (G_OBJECT (main_window), "destroy", G_CALLBACK (destroy), NULL); | |
gtk_widget_realize(main_window); | |
gtk_widget_show_all(main_window); | |
printf("[+] created GTK widget\n"); | |
flash_plugin_handle = loadFlashPluginSo(); | |
loadNPEntryPoints(flash_plugin_handle); | |
printf("[+] initialized flash plugin entry points\n"); | |
initNPNetscapeFuncs(&browserFuncs); | |
printf("[+] initialized browser functions\n"); | |
checkError("NP_Initialize", iNP_Initialize(&browserFuncs, &pluginFuncs)); | |
printPluginEntrypoints(&pluginFuncs); | |
NPWindow *npwin = npwindow_construct(main_window); | |
printf("[+] created NPWindow widget\n"); | |
NPP_t *instancep = malloc(sizeof(NPP_t)); | |
memset(instancep,0,sizeof(sizeof(NPP_t))); | |
NPP instance = instancep; | |
NPSavedData* saved = malloc(sizeof(NPSavedData)); | |
memset(saved,0,sizeof(sizeof(NPSavedData))); | |
stream = npstream_construct(); | |
uint16_t stype; | |
char *xargv[]= {"src", "menu", "quality", "bgcolor", "name", "allowscriptaccess", "type", "pluginspage", "align", "height", "width"}; | |
char *xargm[]= {URL, "false", "high", "#ff00ff", "bmxbackflips", "sameDomain", "application/x-shockwave-flash", "http://www.macromedia.com/go/getflashplayer", "middle" , "435", "580"}; | |
checkError("NPN_New", pluginFuncs.newp("application/x-shockwave-flash", instance, NP_EMBED, 0, xargv, xargm, 0)); | |
checkError("NPN_SetWindow", pluginFuncs.setwindow(instance, npwin)); | |
checkError("NPN_NewStream", pluginFuncs.newstream(instance, "application/x-shockwave-flash", stream, 0, &stype)); | |
FILE *pp; | |
char buffer[8192]; | |
if(strstr(argv[1],"http:") == argv[1]) { | |
sprintf(buffer, "wget %s -q -O -", argv[1]); | |
pp = popen(buffer, "r"); | |
} | |
else | |
pp = fopen(argv[1],"rb"); | |
int len; | |
while((len=fread(buffer, 1, sizeof(buffer), pp)) != 0) { | |
pluginFuncs.writeready(instance, stream); | |
pluginFuncs.write(instance, stream, 0, len, buffer); | |
} | |
if(strstr(argv[1],"http:") == argv[1]) | |
pclose(pp); | |
else | |
fclose(pp); | |
checkError("NPN_DestroyStream",pluginFuncs.destroystream(instance, stream, NPRES_DONE)); | |
free(stream); | |
gtk_main (); | |
checkError("NPN_Destroy",pluginFuncs.destroy(instance, &saved)); | |
checkError("NP_Shutdown", iNP_Shutdown()); | |
dlclose(flash_plugin_handle); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment