How to compile .sh script using g++?

Hi guys,

Can you please help with compiling 123.sh file using g++?

The idea is to make 123.sh not readable (make it kind of binary).
Is there any idea ho to achieve this?

It's a bash script. Shell scripts do not need compilation.
What do you want to do? Be able to run the script from
your program?

Shell scripts do not work that way.

Shell scripts do not work this way. There used to be a tool to do this, but it's become well known that all it does is feed the decrypted program into the shell as plaintext -- as it has to, for it to work at all!

Programs do not work that way.

That's a two step process:
step 1: reimplement your script in C++
step 2: compile it with g++

Step 1 might be quite complex depending on both the script itself and your C++ skills.

In any case, whatever the kind of executable, nothing will prevent a determined user to reverse engineer it.

What makes you think you can send code of any kind to someone else's computer in such a way they can't see how your code works?

1 Like

Or, to turn that around:

Would you want people to be able to do that to you? Run completely anonymous code which can't be tracked, analyzed, controlled, accounted, reviewed, or trusted in any way? It's their computer. If you need to control access so completely that chmod isn't good enough for you, make them use yours, and don't give them the keys.

1 Like

IF you want to maintain code provided as a vendor, and keep the customer from copying it, you can use shc. It has issues but is meant to do what Visual Basic did back in the '90's - keep compiled code safe from piracy - reverse engineering.

Francisco Rosales, home page

And how well did that work?

Hi guys.
Thanks everyone for the answers.
The idea is to not allow ppl see the code itself but allow them to use script.
I've found shc but didn't use it yet. Furthemore I red that its possible to decompile scripts ))
So, there no way to keep the CODE not visible to others?

If someone is interested enough it is impossible to keep the instructions contained in code that they are running locally from them in any language.

The degree of difficulty in decompiling a C++ program is obviously greater than that of decompiling a shell script, (no smart remarks about Perl please), but ultimately the user has to be able to read the file they are executing.

It is possible to respond to authenticate a remote request and execute it thus denying the user access to the executable they are running (though to be pedantic it it the application server that runs the code in this instance).

How could a computer possibly run anything without decoding it?

How could you possibly decode it without giving the computer(and anyone who cares to watch) clear instructions on how to do so?

We get these threads all too often. It frequently takes pages of hilarious rube goldberg machine proposals for people to realize the futility.

This is the reason one should only use free software, so my
computing is not being controlled by somebody else and
I become dependent on it.

shc encrypts the shell commands and arguments so that you cannot use the strings command to see what the script is doing.

If you use a disassembler and spend many hours you can resurrect the shell script.
However, I have never seen a shell script so incredibly new and wonderful that would necessitate that effort. If you know what files a script messes with, and you can view an input file and an output file (for example) you can build your own without going through all the troubles of disassembling code.

The people who would feel the need to steal the code can't really program to start with. And if someone stole your whole app and marketed it as if they owned it, he/she could never support it.

@Achenle

It worked for simple scripts. I had trouble getting it to compile and run correctly on Solaris. More of a toy than a tool IMO. I cannot think of a valid application for it offhand.

And it is not C++, just C, so you need a C compiler, gcc, not g++.

From previous reiterations of this eternally popping up thread, I recall that it feeds the script into /bin/sh as plaintext. Might take a little fiddling with a chroot or something like strace to dump it but doesn't sound anywhere near as bad as disassembly. [edit] interesting, it pre-emptively ptrace's itself so other things can't.

Hi.

In post #4, jlliagre suggested the only method that I can think of. Building on his suggestion, you could set the permissions of the executable to execute-only. Then, if run only on a machine where you have control over the file, no real information can be obtained. Here's an example, showing that the file can only be executed, and the system calls traced, but nothing else (and, of course, if you can't read it, you can't copy it):

#!/usr/bin/env bash

# @(#) s1	Demonstrate execute-only file.

# Utility functions: print-as-echo, print-line-with-visual-space, debug.
# export PATH="/usr/local/bin:/usr/bin:/bin"
LC_ALL=C ; LANG=C ; export LC_ALL LANG
pe() { for _i;do printf "%s" "$_i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }
db() { ( printf " db, ";for _i;do printf "%s" "$_i";done;printf "\n" ) >&2 ; }
db() { : ; }
C=$HOME/bin/context && [ -f $C ] && $C file objdump gdb strace

FILE=${1-t.c}

pl " Input c source file $FILE:"
cat $FILE

pl " Results:"
gcc $FILE
ls -lgG a.out

pl " Execute only results:"
chmod 111 a.out
ls -lgG a.out
./a.out

pl " Results, attempt to read a.out with file, objdump:"
file a.out
objdump -s a.out

pl " Results, debug execution of execute only file:"
gdb ./a.out </dev/null

pl " Results, trace execution of execute only file, I/O calls:"
strace ./a.out 2>&1 |
egrep 'open|close|read|write'

exit 0

producing:

$ ./s1

Environment: LC_ALL = C, LANG = C
(Versions displayed with local utility "version")
OS, ker|rel, machine: Linux, 2.6.26-2-amd64, x86_64
Distribution        : Debian 5.0.8 (lenny, workstation) 
bash GNU bash 3.2.39
file - ( /usr/bin/file, 2008-09-08 )
objdump GNU objdump (GNU Binutils for Debian) 2.18.0.20080103
gdb GNU gdb 6.8-debian
strace -- version 4.5.17

-----
 Input c source file t.c:
#include <stdio.h>
#include <string.h>
#define VERSION  "1.0"
#define PROGRAM  "main"

int
main (int argc, char *argv[])
{
  {				/* separate scope for version processing */
    char *ver = "--version";
    if (argc == 2 && (strstr (ver, argv[1]) != NULL))
      {
	printf ("%s %s\n", PROGRAM, VERSION);
	return 0;
      }
  }
  int j = 1;
  printf (" Hello, world from c: %s, %s.\n", PROGRAM, VERSION);
  while (--argc > 0)
    printf ("(%d) %s%s", j++, *++argv, (argc > 1) ? " " : "");
  printf ("\n");
  return (0);
}

-----
 Results:
-rwxr-xr-x 1 9290 Oct 23 10:33 a.out

-----
 Execute only results:
---x--x--x 1 9290 Oct 23 10:33 a.out
 Hello, world from c: main, 1.0.


-----
 Results, attempt to read a.out with file, objdump:
a.out: executable, regular file, no read permission
objdump: a.out: Permission denied

-----
 Results, debug execution of execute only file:
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu"...
./a.out: Permission denied.
(gdb) quit

-----
 Results, trace execution of execute only file, I/O calls:
open("/etc/ld.so.cache", O_RDONLY)      = 3
close(3)                                = 0
open("/lib/libc.so.6", O_RDONLY)        = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\300\342\1\0\0\0\0\0@"..., 832) = 832
close(3)                                = 0
write(1, " Hello, world from c: main, 1.0.\n"..., 34 Hello, world from c: main, 1.0.

However, I think this is an XY problem. You want to do X, and your solution is Y: making the file unreadable. You said that you don't want others to see your code, but you have not told us why not.

Best wishes ... cheers, drl

Oh yes they can. That's almost trivial to work around. LD_PRELOAD can be used to load a library that preemptively intercepts system calls and returns what's needed to keep the obfuscated script running despite it being traced already. Worst case you can write you own kernel module that fudges the return values of system calls as necessary to keep the traced obfuscated script running.

That doesn't prevent tools that do not care about whether a process is ptraced or not to trace it anyway like dtrace, systemtap, sysdig or similar.

Guys, thanks to all for your replies, problem solved.