logo logo

 Back to main page

The NWNX Community Forum

 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
 
Run nwnScript from outside game - Proof of Concept
Goto page Previous  1, 2, 3  Next
 
Post new topic   Reply to topic    nwnx.org Forum Index -> Windows development
View previous topic :: View next topic  
Author Message
PlasmaJohn



Joined: 04 Mar 2005
Posts: 70
Location: The Garage

PostPosted: Sat Jan 07, 2006 21:29    Post subject: Reply with quote

PlasmaJohn wrote:
BTW, this should be usable via the following code:

Code:
int (*pExecuteScript)(char**,int,int) = 0x05af2c0;

int MyFunc( /* other args */, int obj ) {
    ...
    (*pExecuteScript)("ext_event",obj,1);
    ...
}

Ok, no joy with this method. I'm no expert on Windoze, so can somebody clue me in how to make this call at this address please?

isilweo wrote:
Some technical part.
ExecuteScript is located on 0x05AF2C0. It takes three parameters on stack and one passed using ecx. Parameters are ExecuteScript(char ** ScriptName, int ObjectId, int Something = 1). Something is always 1 when running script, maybe that function is used for something else when something!=1 - i don't know. In EAX there's pointer to static variable which probably contains ScriptResult (or something like that). Can't tell you address right now cause i'm not at my computer.
Back to top
View user's profile Send private message
PlasmaJohn



Joined: 04 Mar 2005
Posts: 70
Location: The Garage

PostPosted: Fri Jan 13, 2006 18:17    Post subject: Reply with quote

*poke-poke-poke-pokety-pokety-poke*

Help?

This is the event injector that I've been looking for for over a year. There are several really cool things it can be used for. For instance: real-time cross-server communication. External AI. Ability to offload complicated computation to an external process or thread.

Anything that you currently poll (Autobic, Vaultster, etc.) can now run a script that lets the engine know that it's done or has encountered an error.
Back to top
View user's profile Send private message
Zebranky



Joined: 04 Jun 2006
Posts: 415

PostPosted: Fri Jul 21, 2006 5:44    Post subject: Reply with quote

After several attempts, I have re-implemented this POC. The following code, included in any NWNx plugin, will execute the script in scriptname. OBJECT_SELF will be the module (the second arg in the pExecScript call).

For the technical: the 1.67 address of the ExecuteScript() function is 0x005baba0. It still takes three arguments as described by isilweo. The argument on ECX is the C++ 'this' pointer. It varies based on NWNx modules loaded, but is always stored in 0x00661b38. This code simply loads that pointer into ECX, then calls the function with the provided args. Many thanks to isilweo for the idea, and PlasmaJohn for part of the implementation, especially realizing that ECX is the 'this' pointer.

Code:
char *scriptname = "arbitrary";
typedef int (__stdcall *ExecFP)(char **, int,int);
ExecFP pExecScript = (int(__stdcall*)(char**,int,int))0x005baba0;

void CNWNXPlugin::Exec() {
   __asm { push esp
      mov ecx, dword ptr ds:[0x00661b38]
      }
   (*pExecScript)(&scriptname,0,1);
   __asm { pop esp }
}
Back to top
View user's profile Send private message Visit poster's website
PlasmaJohn



Joined: 04 Mar 2005
Posts: 70
Location: The Garage

PostPosted: Fri Jul 21, 2006 14:22    Post subject: Reply with quote

Ooh, thanks for the 167 addresses.

I know I made a post awhile ago about this, must have gotten lost in the crash. Getting this to work is a big first step, however there's another thing that needs to be dealt with. The script engine can only run in one thread at a time, so something needs to manage the locking. Probably the best place for that would be ResMan as that inserts itself into between script call and script execution.
Back to top
View user's profile Send private message
virusman



Joined: 30 Jan 2005
Posts: 1020
Location: Russia

PostPosted: Fri Jul 21, 2006 17:38    Post subject: Reply with quote

PlasmaJohn wrote:
Ooh, thanks for the 167 addresses.

I know I made a post awhile ago about this, must have gotten lost in the crash. Getting this to work is a big first step, however there's another thing that needs to be dealt with. The script engine can only run in one thread at a time, so something needs to manage the locking. Probably the best place for that would be ResMan as that inserts itself into between script call and script execution.
No, Resman hooks the LoadResource function (or something like that).
RunScript calls LoadScript (-> LoadResource) and then ExecuteScript. ExecuteScript is hooked by Profiler.
But it doesn't matter in this case. Just calling RunScript works ok.
Btw, what are you trying to do? If you want to run nwscripts from nwnx-plugin, just look at the Chat plugin sources.

Code:
// 53 55 56 57 8B 7C 24 14 8B F1 8B CF
DWORD FindRunScript()
{
   char* ptr = (char*) 0x400000;
   while (ptr < (char*) 0x600000)
   {
      if ((ptr[0] == (char) 0x53) &&
         (ptr[1] == (char) 0x55) &&
         (ptr[2] == (char) 0x56) &&
         (ptr[3] == (char) 0x57) &&
         (ptr[4] == (char) 0x8B) &&
         (ptr[5] == (char) 0x7C) &&
         (ptr[6] == (char) 0x24) &&
         (ptr[7] == (char) 0x14) &&
         (ptr[8] == (char) 0x8B) &&
          (ptr[9] == (char) 0xF1) &&
          (ptr[10] == (char) 0x8B) &&
          (ptr[11] == (char) 0xCF)
         )
         return (DWORD) ptr;
      else
         ptr++;
   }
   return NULL;
}

void RunScript(char * sname, int ObjID)
{
  int sptr[4];
  sptr[1] = strlen(sname);
  _asm {
    lea  edx, sptr
    mov  eax, sname
    mov  [edx], eax
    push 1
    push ObjID
    push edx
    mov ecx, pScriptThis
    mov ecx, [ecx]
  }
  scriptRun = 1;
  pRunScript();
  scriptRun = 0;
}

int HookFunctions()
{
  DWORD org_Run  = FindRunScript();
}
(c) dumbo
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
PlasmaJohn



Joined: 04 Mar 2005
Posts: 70
Location: The Garage

PostPosted: Fri Jul 21, 2006 21:37    Post subject: Reply with quote

virusman wrote:
Btw, what are you trying to do? If you want to run nwscripts from nwnx-plugin, just look at the Chat plugin sources.

What we're trying to do is to run scripts in response to external stimuli, like a web page, or an IM application without requiring the VM to poll. I'd be just as happy with plugin code that'll add an event to the event queue.

The nwnx_inject plugin starts a new thread and listens for external events on a configurable UDP port. Using the addresses that Zebranky found, we can call the RunScript(?) function from that thread and not have to wait for the script VM to get around to polling for new events. The problem is that if the inject thread tries to enter RunScript while the thread that the script VM is running in is doing the same, bad thing happen. So we need to synchronize between them.

Anything that hooks RunScript, is a good place to manage that mutex. I think.
Back to top
View user's profile Send private message
virusman



Joined: 30 Jan 2005
Posts: 1020
Location: Russia

PostPosted: Fri Jul 21, 2006 21:51    Post subject: Reply with quote

PlasmaJohn wrote:
The problem is that if the inject thread tries to enter RunScript while the thread that the script VM is running in is doing the same, bad thing happen. So we need to synchronize between them.

Anything that hooks RunScript, is a good place to manage that mutex. I think.
Have you tried it or it's just an assumption?
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
PlasmaJohn



Joined: 04 Mar 2005
Posts: 70
Location: The Garage

PostPosted: Fri Jul 21, 2006 22:26    Post subject: Reply with quote

virusman wrote:
Have you tried it or it's just an assumption?

Tried what? Crashing the server? Yes, quite spectacularly as expected. If it were stable I'd be using it.

Hooking nwnx_chat? No, first time I've seriously considered it and I haven't touched NWNX code in months.
Back to top
View user's profile Send private message
chaoslink



Joined: 23 Aug 2006
Posts: 37

PostPosted: Thu Aug 24, 2006 0:01    Post subject: Reply with quote

Why not hook into RunScript like how ResMan hooks DemandRes?

You could make that hook code the synchronization point for both script execution mechanisms.

[edit: oops, I realize that's what the above post was saying, sorry]
Back to top
View user's profile Send private message
Zebranky



Joined: 04 Jun 2006
Posts: 415

PostPosted: Thu Aug 24, 2006 4:14    Post subject: Reply with quote

I might have gotten this mutex working... I just need to be able to test it. Implementing a mutex on hooked nwserver code is cake compared to dealing with MFC and the Windows API... Rolling Eyes
Back to top
View user's profile Send private message Visit poster's website
chaoslink



Joined: 23 Aug 2006
Posts: 37

PostPosted: Thu Aug 24, 2006 9:04    Post subject: Reply with quote

Gah, you're telling me! Why your bothering with that junk is beyond me Wink

I may write my own version of this that compiles for both windows and linux (there seems to be a general lack of portable code around here).
Back to top
View user's profile Send private message
Zebranky



Joined: 04 Jun 2006
Posts: 415

PostPosted: Fri Aug 25, 2006 4:32    Post subject: Reply with quote

Hey, it's still a POC. I can write nasty non-portable code if I want to. Wink

I actually can't reproduce that crash, though...
Back to top
View user's profile Send private message Visit poster's website
Zebranky



Joined: 04 Jun 2006
Posts: 415

PostPosted: Mon Aug 28, 2006 6:08    Post subject: Reply with quote

This is in live testing in an isolated area on Hades. An NPC is speaking a one-liner every tenth of a second without problems.
Back to top
View user's profile Send private message Visit poster's website
chaoslink



Joined: 23 Aug 2006
Posts: 37

PostPosted: Tue Aug 29, 2006 0:56    Post subject: Reply with quote

Zebranky wrote:
Hey, it's still a POC. I can write nasty non-portable code if I want to. Wink

I actually can't reproduce that crash, though...


Muahahaha!
Back to top
View user's profile Send private message
Zebranky



Joined: 04 Jun 2006
Posts: 415

PostPosted: Tue Aug 29, 2006 4:14    Post subject: Reply with quote

Curses. After 24 hours, 16 minutes, and 43 seconds, it failed miserably. Back to the drawing board (or IDE, as the case may be).
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    nwnx.org Forum Index -> Windows development All times are GMT + 2 Hours
Goto page Previous  1, 2, 3  Next
Page 2 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group