#Allow input to be programmatically passed to an interactive program without needing explicit support

1 messages · Page 1 of 1 (latest)

sly rover
#

Note: The title of this feature suggestion might be slightly misleading as I was not able to phrase it properly due to title length limitations. Please read this message fully to understand what this feature suggestion is about.

Feature suggestion

Allow input to be programmatically (i.e. via GreyScript code) passed to a program without needing the program's developer to add explicit support for it (i.e. via custom objects).

Reason for suggesting this feature

Currently, most tools in Grey Hack are interactive (meaning that they use the user_input function instead of launch parameters to receive user input), it would be nice if there was a way for the user_input function to return not just input manually entered in by the player via the terminal, but also input passed via GreyScript code (if any). This would allow for more flexibility in automation.

For example, in real life, a command-line program usually expects input via stdin, this allows input to be programmatically (i.e. via code) passed to the program by writing to its stdin buffer. In this case, input can be passed to that program programmatically without waiting for its developer to explicitly add support for programmatically passing input to it.

What the end result of implementing this feature might look like

// A simple script (written in GreyScript) that automates the process of passing input to an interactive program (called 'interactive-cli' in this case) that receives input via the `user_input` function instead of launch parameters.

launch(
  "/usr/bin/interactive-cli",
  "",
  // A 3rd parameter could be added to the `launch` function that allows input that will be passed to the `user_input` function to be specified.
  "command-1\ncommand-2 arg-1\ncommand-3"
)

For further reference

Link to the starting comment of a discussion regarding this feature suggestion: #coding message

sly rover
#

On 2nd thought, I'm thinking that it might be better if each in-game process's input and output buffers could be exposed via the GreyScript API?

half pebble
#

i think this is a limitation of the underlieing scripting language... but i am iffy on that

marble karma
sly rover
marble karma
#

Yeah sure I get that but like if you want automation then just write your own program....

sly rover
sly rover
#

unlike a library, a program can't just be imported into your script (unless you have access to its source code), so allowing players to do this would expand automation capabilities

#

plus the player wouldn't be tied to a single tool's (i.e. Viper's, Omni's) macro system (assuming that the tool even provides a macro system in the first place)

humble niche
#

exposing input/output buffers will require mutex locking in the interpreter since other processes can read/write to these buffers, this is extremely complicated to manage in a language like miniscript, if it was added on't expect something like this anytime soon

#

or at all

#

You can easily crash the interpreter

sly rover
#

i see, in that case, an alternative method of implementing this feature could be considered but would require a solid understanding of the game's relevant internals in order for me to provide a feasible implementation suggestion

#

where does the user_input function get its return value from under the hood? just asking in case anyone has looked through this part of the game's code before

sly rover
humble niche
#

once sec

humble niche
#

you can override intrinsic functions

#

close to function hooking

#

but you still have the memory space issue

sly rover
#

so like hooking the print and user_input functions of a program launched using the launch function

sly rover
sly rover
humble niche
#

I know exactly what your trying to do, I doubt support for actual trampolining functions in a running process will be added

#

it's undefined behavior

#

However, making a launch script a child process, would allow sharing of memory

#

so both scripts share the same memory space

sly rover
humble niche
#

otherwise just use get_custom_object

sly rover
humble niche
#

but your wanting to alter not just the state but the actual code of a running process

#

atm, from what I can tell every launched script has it's own process and memory

sly rover
sly rover
# humble niche otherwise just use get_custom_object

yes but that would mean that the developer of the launched program would have to explicitly add support for passing input to the program via code instead of manually through the terminal, the purpose of this feature suggestion in the first place is to eliminate this dependency

humble niche
#

Would simply allowing scripts to return values, eg like functions solve your problem?

#

would like get_terminal_text be enough?

sly rover
humble niche
#

tldr, can you explain the problem again sorry

sly rover
# humble niche would like get_terminal_text be enough?

the problem is that launch is a synchronous function that blocks until the entire program has finished executing, but the program might make multiple calls to the print function in which case the terminal output text will differ at different points of that program's execution

humble niche
#

You want async output to another program?

sly rover
#

i just want the parent process to be able to execute some custom logic when the child process (i.e. the program it launched using the launch function) calls the print and/or user_input functions

humble niche
#

You want to inject custom logic into a process/script you don't own, correct?

sly rover
humble niche
#

can you give me an example of a use case

#

kinda having a hard time following why you would need this kind of complex logic

sharp torrent
#

So, because it's synchronous execution, you'd need the child process to have custom behavior on print/user_input, cause the main processes is blocked at those points. That "custom" behavior would need to be strictly defined by the game though. Allowing the launching script to just inject its own function into the launched script would have some pretty nasty security implications.

humble niche
#

You just reexplained everything we talked about, I wanted an actual use case

sharp torrent
#

Arcane hasn't been super clear if thet want custom functionality in the print, or just a way to later interact with it, without printing, so I was just explaining the security limitation of using a fully custom print implementation.

As for use case, I use it for handing off batch scan/deciphers to subprocesses so I can carry on with my business while they decipher, and just populate the main script as they finish. But that does hinge more on the usefulness of the multithreadding bit than the IPC

humble niche
#

create two files mem1.txt and mem1.lck

#

if mem1.lck is present then some script is using the resource

#

simulates a lock

#

so spin lock wait until it's not present

#

A string is also simply an array/list of bytes, so you can write ByteBuffers

#

in miniscript

#

so if players see mem1.txt it's just bytes

#

for ICP across systems, you can create services that allocates values on the global get_custom_object map

#

that's how alteast I do async process comm

sharp torrent
#

Yep. Everything talked about so far is very possible to implement already. The only issue comes from them wanting to do it with binaries they didn't write. Lol

humble niche
#

Ya, adding function hooking on scripts you don't own is going to be death for new players

sly rover
# humble niche Ya, adding function hooking on scripts you don't own is going to be death for ne...

if the print/user_input function is only hooked during the call to the launch function, how would this be a security issue/liability?

if the player runs the program that's hooking the calls to those functions, then yes it could be a security issue (originating from user error rather than an issue with this feature), but at that point, whether the program hooks those functions would be the least of their concerns since the program could already do anything malicious without hooking those functions (since the player allowed the program to run on their in-game computer)

#

to be clear, what i'm suggesting currently is to provide a way (via the GreyScript API) for the parent process to be able to execute some code when the child process (i.e. the program it launched using the launch function) calls the print and/or user_input functions, the modified print and user_input functions should be restored to their original versions (i.e. whatever they were set to before the call to the launch function) after the call to the launch function ends

sharp torrent
#

If you can replace the child's print function with your own custom logic, it becomes a security problem, cause that's executed in the called scripts runtime, so you can just walk the whole global map and do naughty things to anything you might find (ie: coin objects, stored infrastructure shells)
If you're just replacing print with a pseudo stdout type deal, that's less of an issue.

humble niche
#

I still don't really understand what you would use this for

sly rover
sharp torrent
#

prints state reverting after execution wouldn't matter, really. The damage is done during execution. You could insert a whole other tool into print, if you wanted.
Image I make a program for crypto gamblng that I distribute to others to play. Now, I'm going to store the coin object in memory to avoid the coin popup every time I wanna do an operation with it. Now bad actors can take my game, launch it with a program that writes custom coin stealing logic into print, and easily hijack the coin.

sly rover
sharp torrent
#

In theory, but that would presumably involve unblocking the parent process, which i would imagine would have other consequences

#

(tbc, I'm not trying to nay-say or anything, just explaining the technicalities)

sly rover
#

i see

sly rover
sudden fog
#

I want to chime in here. A very big issue I would have with being able to inject code into a script that was not specifically coded to allow it is it would make running a bank impossible (as Tanshy pointed out).

#

if you can just inject whatever code you want in 1337coins app, then everyone who banks there is hosed.

#

but if the change is only allowing user input to be passed, fine.

sly rover
# sudden fog I want to chime in here. A very big issue I would have with being able to inject...

although i forgot to mention this initially, the injected code was supposed to run in the parent process’s context instead of the child process’s context so that the parent process would not be able to access the child process’s memory via the injected code, however, implementing this might not really be feasible so that’s why i’m trying to figure out an alternative way to achieve the intended goal of this feature suggestion

humble niche
#

if you would give me a use case, an example of what you would use this feature for, I could help you figure out a workaround

neat pike
#

input = user_input(">")
while (input != "exit")
code
end while

nova crag
sly rover
sudden fog
#

So I was messing around with a way to remote control a 5hell session using a shared file. Works great until, dun dun dun, user input is required. So yeah, now I see a definite use for something like what you suggest.

Then I was thinking, "how can we make it safe." And I couldn't think of something that couldn't also be open to a hack.

And then I thought, let it be open to attack! There was already some wiff of a mention about process injection. Maybe get a shell on a system and inject into the Terminal.exe. The inject causing input to be immediately sent to that Terminal.exe (essentially injecting into bash. So if the target is on a user_input prompt when the attack is run, the attack enters the user_input. Would work wether the target is in bash or another script since bash would be a script by the time this were to be possibly implemented.

So like, instead of adding a way to alter how scripts that are already written operate, we change Terminal.exe to be able to be hacked and have input injected into it. A feature that would be both a utility feature, as well as an attack vector, just like rshells.

#

could make an entire object API around running processes. hackable like overflow attacks with different possible return values.

one could be a vuln that allows you to snoop user input into a process.

another could allow snooping output (prints)

and another could inject input

and another could kill the process (if it gets also the correct permission level)

nova crag
# sudden fog So I was messing around with a way to remote control a 5hell session using a sha...

That sounds like a cool feature, I will just mention though, with the way terminals, user input, processes, and scripts interact on the backend, it may be extremely difficult or nigh impossible for something like that to be implemented. It was already quite hard for the new bash system to handle some of this stuff, and even with that there's still some issues with processes I believe

sudden fog
#

yeah, i tend to dream big.

#

lol

#

totally understandable. the terminal isn't a real terminal in the first place. so yeah, lots of work. maybe too much.

#

prototype

nova crag
sly rover
humble niche
#

this is for input injection blocking

#
pPrint = @print
print = function(value)
    pPrint("x " + value)
end function
#

@sudden fog because you can do this you can actually just validate the first arg of user_input, and any vuln would be useless

humble niche
sly rover
humble niche
#

No because each process uses an isolated MiniScript VM

sly rover
#

i see

humble niche
#

They would have to run within the same VM

#

and not be async

sudden fog
sudden fog
humble niche
sudden fog
#

yes. it is still required to be coded into the script.

#

so no altering other's scripts

#

which would be bad and i wouldn't support that

humble niche
#

Ya, but I think that's what Arcane wants

sudden fog
#

i couldn't run 1337coin if that were possible

#

yeah but that would be bad

humble niche
#

I agree

sudden fog
#

but alternatives would be good

#

globals.input_buffer = ["foo", "bar"]

_user_input = @user_input
user_input = function(prompt,is_pass)
  u_input = ""
  if globals.input_buffer.len > 0 then 
    u_input = globals.input_buffer.pull 
    if is_pass and typeof(u_input) == "string" then u_input = "*"*u_input.len
  else 
    u_input = _user_input(prompt,is_pass)
  end if
  return u_input
end function
sly rover
# sudden fog so no altering other's scripts

although the 2nd suggested implementation of this feature suggestion would effectively allow this (which i only realized at a later stage), this feature suggestion does not intend for other people’s scripts to be altered at will

sly rover
humble niche
#

eg an Dictionary

sly rover
humble niche
#

yes, because it's in C#, it's memory is outside of the VMs

#

it's also managed outside of the VMs

sly rover
#

could each terminal’s input and output buffers be represented in such a manner instead?

humble niche
#

No, because get_custom_object's context is from the initially launched script, as the api docs say launching a script is blocking. the get_custom_object "dictionary" isn't thread safe

sly rover
humble niche
#

they run async

#

depending on impl it could be OS threads or coroutines

sly rover
#

i see

sly rover
sly rover
humble niche
#

It's fine for it to not be thread safe because launching a script isn't async

#

and the values in get_custom_object are only shared between scripts when the initial script calls launch

sly rover
humble niche
sly rover
humble niche
#

might as well pass the "injected" user input as params

sly rover
humble niche
#

What you want too do is weird, cause your wanting to pass a value to user_input before user_input is actually called

sly rover
#

the suggested terminal input buffer was intended to store both data manually entered by the player and data provided by the parent process

humble niche
#

but input is blocking, the script yields until input packet is received

sly rover
#

tbf the input data could just be passed as an additional parameter to the ‘launch’ function perhaps

sly rover
humble niche
#

either case, the owner of said script your providing input too has to now consider invalid input being passed by any other script

#

I wouldn't suggest or develop a system that places validation responsibility on every scripter

#

😒

sly rover
humble niche
#

In either case, you'll still need the owner to handle stuff

sly rover
humble niche
#

if my tool is private I cba to account for other peoples injected input

sly rover
sly rover
humble niche
#

Just suggest too the dev a universal way to provide default input to user_input

#

as long as it's not provided to an already running script

sly rover
humble niche
#

Your solid then

nova crag
sly rover
sly rover
nova crag
#

Or you're saying it would keep a buffer of the string

#

and remove the parts it uses

sly rover
#

maybe there would be an index that is incremented as characters are read from the provided input data

humble niche
#

Just use a stack and push/pop