0

I have a shell (.sh) file that it is multi-line and has functions inside it as a string and I want to execute it entirely without the need to write it to to a .sh file.

  • I tried with Process process = Runtime.getRuntime().exec(commands) and the ProcessBuilder but it was never executed correctly and I was not able to get the error message.
  • I also tried with su cat << EOF commands_here EOF but also never finished

I believe the error comes because it has functions inside it and not only one command per line. Is there a way to execute such shell's string without the need to write it to disk and using ./file.sh?

Kamo
  • 3
  • 1
  • It really depends on what the semantics of your script are. You can pipe your file into bash, but it won’t be the same as running from a file. – Boris the Spider Apr 15 '22 at 06:20
  • @BoristheSpider the idea is that the user receives the shell as a string from server, so I don't want to write it to any file in memory, because it can be dumped, so even pipe will help in my scenario? – Kamo Apr 15 '22 at 06:24
  • Once the server sends something to the client, the client owns it. No amount of security though obscurity will help I’m afraid. Write it to a temp file. – Boris the Spider Apr 15 '22 at 06:25
  • Actually that what I do currently, but still I believe executing it directly in code could be more secure to defend against memory dumping for deleted files. – Kamo Apr 15 '22 at 06:28
  • 2
    You're worried about the wrong things. If you don't trust the other apps on the phone, all files in ANdroid are restricted to your app only by default, so its safe. If you don't trust the user, there's dozens of ways he can get at your script that you can never protect against. Especially on an emulator, he can build a custom OS image that logs everything in the shell to disk. Or do the same with the network subsystem. There is nothing you can do that will protect any info held in ram or on disk from a person who physically controls the hardware. – Gabe Sechan Apr 15 '22 at 06:49
  • But I don't think you'll get a shell script to run via Runtime.exec() because that doesn't run a shell. It runs the app directly. You 'd have to run bash as the app and pipe the file to its stdin. – Gabe Sechan Apr 15 '22 at 06:51
  • @GabeSechan, thank you for lighten this point, my current concern is about the memory dump, and if that is not possible in java/kotlin with Runtime, I will try with c++ as in this answer https://stackoverflow.com/a/25092128/18809987 – Kamo Apr 15 '22 at 07:00
  • You can do it that way with exec- the app you run would be bash (not the script itself). The call returns a Process object, which has a field with the outputStream to send data to that app. Send the script over that stream. – Gabe Sechan Apr 15 '22 at 07:11
  • @Gabe Sechan, can you please include a snippet code or example of that? – Kamo Apr 15 '22 at 07:16
  • Yes, that’s exactly what I said in [my comment](https://stackoverflow.com/questions/71880677/how-to-execute-a-full-shell-string-without-writing-it-to-a-file#comment127020120_71880677) - you can pipe the script into bash. But as I also mentioned, the behaviour of bash will be different - so don’t expect it to “just work”. – Boris the Spider Apr 15 '22 at 07:48
  • @Boris the Spider can you please provide a code example? – Kamo Apr 15 '22 at 07:59

1 Answers1

0

The safest way to achieve this in android is to:

  1. Encode your commands to base64 then apply
  2. Apply a command that decodes them and executes them

Here is a code example:

val b64 = Base64.encode(allCmds.toByteArray(), Base64.DEFAULT)
                            .toString(Charsets.UTF_8).trim()
b64 = b64.replace("\n", "")
var exitValue = 0
try {
    p = Runtime.getRuntime().exec("su -c echo $b64 | base64 -d | sh")
    exitValue = p.waitFor()
} catch (e: Exception) {
    exitValue = 1
}

return exitValue // the value 0 indicates normal termination
Jagar
  • 777
  • 9
  • 24
  • Note this pipes the script into the shell - the semantics of this are different to the shell executing a script from a file. Certain things won’t work as expected - especially anything related to stdin, pids or shell exit behaviour. – Boris the Spider Apr 16 '22 at 11:04
  • @BoristheSpider thanks for your addition, I was testing it with basic usages including loops, if statements, and functions and it worked better than a number of other approaches. – Jagar Apr 16 '22 at 12:50