We help IT Professionals succeed at work.

Compiling and producing an exe

Simon336697
Simon336697 asked
on
Hi guys hope you can help.

Im a total newbie to this, so please bear with me.

I have a file with a .c extension.

Let's say it is called

tobeexe.c

I want to turn this .c file into an executable to run on a windows machine.

I think i have to use a compiler like...

gcc -o tobeexe tobeexe.c

I ran this on a linux box and this makes a file called tobeexe

Can I do this guys, and what other steps do I need to do in order to produce an exe file to run this on a windows machine?

Thank you.
Comment
Watch Question

CERTIFIED EXPERT
Top Expert 2009
Commented:
You have to get a Windows compiler (with IDE preferably). Popular ones are either Visual C++, or Dev-C++.

The latter can be downloaded from :

        http://bloodshed.net/devcpp.html

(it is based on the Mingw port of the gcc compiler).


Once you've chosen a compiler, you can simply create a source .c file and then compile it. A .exe file will be created which you can then execute.
evilrixSenior Software Engineer (Avast)
CERTIFIED EXPERT
Commented:
>> Can I do this guys, and what other steps do I need to do in order to produce an exe file to run this on a windows machine?

It depends what compiler you are using. If you have a Microsoft compile installed you can either make a project and include this file and build it or from the command line type: -

cl tobeexe.c

With Visual Studio 2005 this will build a .exe file called tobeexe.exe

NB. Older compilers may have slightly different command line syntax.

I think without more info from you that's the best answer I can give at this time.
evilrixSenior Software Engineer (Avast)
CERTIFIED EXPERT

Commented:
Command line syntax for Microsoft's compiler (CL): -
http://msdn2.microsoft.com/en-us/library/610ecb4h.aspx
Commented:
If you want to do it on Windows in a Linux-like manner, install Cygwin from http://www.cygwin.com.

Author

Commented:
Hi guys!
Thank you so much for your help to ALL of you.

Guys, the file I have to work with is a <file>.c file.

From my reading (if you could confirm), do I have to do the following?

I have a linux and windows box, so I tried this on my linux box....

1) Make an object file.

gcc -o <filetomake> tobeexe.c

2) Something called a linker or something which makes the exe?

Sorry having problems here..
evilrixSenior Software Engineer (Avast)
CERTIFIED EXPERT

Commented:
The linker is being run for you. The -o option on gcc tells it to invoke the linker and generate an output file, which will be the executable.
evilrixSenior Software Engineer (Avast)
CERTIFIED EXPERT

Commented:
>> The linker is being run for you. The -o option on gcc tells it to invoke the linker and generate an output file, which will be the executable.
This is default behavior unless you provide the -c flag, which tell sit to only compile but not link.
-c 
Compile or assemble the source files, but do not link. The compiler output is an object file corresponding to each source file. 
 
-o file 
Place output in file file . This applies regardless to whatever sort of output GCC is producing, whether it be an executable file, an object file, an assembler file or preprocessed C code. 

Open in new window

CERTIFIED EXPERT
Top Expert 2009

Commented:
The same will be true on Windows ;) Just try it, and you'll see how easy it is :)

Author

Commented:
Hi Infinity08.
I ran this on linux, and it produced a file.
[root@rupert temp]# gcc -o <filetomake> <file>.c --sysroot=/temp/head/
exe2perl.c:16:19: error: stdio.h: No such file or directory
exe2perl.c:17:20: error: stdlib.h: No such file or directory
exe2perl.c:18:23: error: sys/types.h: No such file or directory
exe2perl.c:19:22: error: sys/stat.h: No such file or directory
exe2perl.c:20:22: error: sys/mman.h: No such file or directory
exe2perl.c:21:19: error: fcntl.h: No such file or directory
exe2perl.c:22:20: error: unistd.h: No such file or directory
exe2perl.c:23:19: error: errno.h: No such file or directory
evilrixSenior Software Engineer (Avast)
CERTIFIED EXPERT

Commented:
What about just : gcc -o <filetomake> <file>.c   ?

Author

Commented:
Hi evil....youre right I did that, but the thing is I dont know how to actually go from there, that is, use the file its created....it doesnt like it accepts any arguments.
evilrixSenior Software Engineer (Avast)
CERTIFIED EXPERT

Commented:
What do you mean "use the file"? Do you mean run it?

./<filetomake>

Will run it.

Author

Commented:
Thx evil :>)

I ran it as you said. it came back with
signature not found, exiting
evilrixSenior Software Engineer (Avast)
CERTIFIED EXPERT

Commented:
Well, I guess that's the behavior of the program you've built. I have no way of knowing what it's meant to do without seeing the source code.

Author

Commented:
Evil can I send you the source code?
evilrixSenior Software Engineer (Avast)
CERTIFIED EXPERT

Commented:
Paste it here under the "Attach Code Snippet" section.
CERTIFIED EXPERT
Top Expert 2009

Commented:
Try something simple first. Create a source file with the following contents, and compile and run it in the same way as said above :


#include <stdio.h>
 
int main(void) {
  printf("Hello world !!");
  return 0;
}

Open in new window

Author

Commented:
Hi Infinity!

[root@rupert temp]# gcc -o runplease helloguys.c
[root@rupert temp]# ./runplease
Hello world !![root@rupert temp]#
evilrixSenior Software Engineer (Avast)
CERTIFIED EXPERT

Commented:
That looks good to me :)
CERTIFIED EXPERT
Top Expert 2009

Commented:
>> Hi Infinity!

Great ... Now we just have to get your program to work ... What code is it ? Did you write it ? Or did you get it somewhere ? What is it supposed to do ?

Author

Commented:
Guys should i post the source code here?
What this is is an exe2perl tool.
I have some perl scripts that have been converted to an exe but I dont have the original perl script, and wish to look at the original perl code to learn from.
CERTIFIED EXPERT
Top Expert 2009

Commented:
oh, btw :

>> [root@rupert temp]# ./runplease

be careful with running things as root, especially if you're not sure what the code will do ... It's best to do your daily work as a different unprivileged user, and use root only for system management tasks.

[/end of side note ;) ]

Author

Commented:
I did not write this exe2perl tool, nor the scripts that have been converted.
It simply is for my own learning, as it is to learn this gcc stuff from you great people here. :>)

Author

Commented:
So the thing is I spose being stupid as I am, when I ran the gcc -o on this exe2perl, it created a file, but I dont know what else it did to my system :<(
Thanks for bearing with me on this everyone.
CERTIFIED EXPERT
Top Expert 2009

Commented:
>> What this is is an exe2perl tool.

This might only work on Windows (after a short look using Google).

Can you post the code ?

Author

Commented:
Okay....ill put it here :>
---------------------------------------------- exe2perl.c
------------------------ start of file...
/******************************************************************************
 * exe2perl (AKA perl2exe v5.xx unpacker)                                     *
 * --------------------------------------                                     *                                        *
 *                                                                            *
 * Compile using the following command: gcc -o exe2perl exe2perl.c            *
 *                                                                            *
 * Distributed under the terms of the GPL v2 licence.                         *
 *                                                                    -- (GM) *
 ******************************************************************************/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
 
 
#define SIGNATURE "dbload 1.0 signature\r\n\r\n\200\200\200\200\200\200\200" \
			"\200\r\n-p2x_noshow_includes  "
#define OUTPUT_SUFFIX ".unpacked"
 
void *
binsearch(void *where, size_t where_size, void *what, size_t what_size)
{
    void *p;
    for (p = where; p <= (where + where_size - what_size); p++)
        if (!memcmp(p, what, what_size))
            return p;
 
    return 0;
}
 
char *
getstr(char *source, size_t source_size)
{
    char *entry_name = source;
    char *entry_name_end = binsearch(entry_name, source_size, "\r\n", 2);
    if (!entry_name_end)
        return 0;
 
    if (!(entry_name =
	    strndup(entry_name, (size_t)(entry_name_end - entry_name))))
        return 0;
 
    return entry_name;
}
 
char *
getblock(char *source, size_t amount)
{
    char *block;
 
    if (!((block = (char *)malloc(amount)) && (memcpy(block, source, amount))))
       return 0;
 
    return block;
}
 
void decrypt_block(char *block, size_t block_size)
{
    const char *crypt_string = "For more information visit www.indigostar.com";
    char *p;
 
    for (p = block; p < block + block_size; p++)
        *p ^= crypt_string[((p - block) % strlen(crypt_string))];
}
 
int make_dir(const char *filename)
{
    char *path, *p, *h;
    size_t path_length;
    int cwd_fd;
 
    if (!(p = strrchr(filename, '/'))) /* there is no leading directory */
        return 0;
 
    if (!(path = strndup(filename, p - filename)))
        return 1;
 
    /* save cwd */
    if ((cwd_fd = open(".", O_DIRECTORY)) == -1) /* Linux-specific */
    {
        free(path);
        return 1;
    }
 
    h = p = path;
    path_length = strlen(path);
    do
    {
        if ((p = strchr(h, '/'))) /* if several directories are given */
            *p = 0;
 
        while (*h == '/') /* we don't want absolute paths */
            h++;
 
        if (!(strcmp(h, "..") && strcmp(h, "."))) /* just a safety measure */
        {
            free(path);
            close(cwd_fd);
            return 0;
        }
 
        mkdir(h, 0777);
        if (chdir(h))
        {
            free(path);
            fchdir(cwd_fd);
            close(cwd_fd);
            return 1;
        }
 
        if (!p) break; /* there was one leading directory */
 
        h = p + 1; /* advance to the next name */
    } while (h < (path + path_length));
 
    free(path);
    fchdir(cwd_fd);
    close(cwd_fd);
    return 0;
}
 
int save_file(const char *name, const char *buffer, size_t buffer_size)
{
   int fd;
 
   if (make_dir(name))
       return 1;
 
   if ((fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0666)) == -1)
       return 1;
 
   if (write(fd, buffer, buffer_size) == -1)
       return 1;
 
   if (close(fd) == -1)
       return 1;
 
   return 0;
}
 
int
main(int argc, char *argv[])
{
    char *source, *p, *output_dir;
    struct stat st;
    int source_fd = 0;
    int cwd_fd = -1;
 
    printf("perl2exe unpacker;  Written by (GalaxyMaster)\n---\n");
 
    if (argc != 2)
    {
        printf("Usage: %s <file>\n", argv[0]);
        return 1;
    }
 
    if ((source_fd = open(argv[1], O_RDONLY)) < 0)
    {
        printf("Error: couldn't open \"%s\" (%s)\n", argv[1], strerror(errno));
        return 2;
    }
 
    if (fstat(source_fd, &st) < 0)
    {
        printf("Error: couldn't stat \"%s\" (%s)\n", argv[1], strerror(errno));
        return 3;
    }
 
    if ((source = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, source_fd, 0))
            == MAP_FAILED)
    {
        printf("Error: couldn't mmap \"%s\" (%s)\n", argv[1], strerror(errno));
        return 4;
    }
 
    printf("Searching...");
    p = (char *)binsearch(source, st.st_size, SIGNATURE,
            sizeof(SIGNATURE) - 1);
    printf("\rSearch result: ");
 
    if (!p)
    {
        printf("signature not found, exiting\n");
        munmap(source, st.st_size);
        close(source_fd);
        return 0;
    }
 
    printf("signature was found at offset 0x%.8X, good! :)\n",
            (size_t)(p - source));
 
    p = p + sizeof(SIGNATURE) - 1; /* skip signature */
    printf("looking for entry file name: ");
    {
        char *name = getstr(p, st.st_size - (p - source));
        if (!name)
        {
            printf("not found, exiting\n");
            munmap(source, st.st_size);
            close(source_fd);
            return 5;
        }
        printf("%s\n", name);
        p = p + strlen(name) + 2; /* advance past entry file name */
    }
 
    if ((cwd_fd = open(".", O_DIRECTORY)) == -1) /* Linux-specific */
    {
        printf("Error: couldn't open current directory (%s)\n",
                strerror(errno));
        munmap(source, st.st_size);
        close(source_fd);
        return 6;
    }
 
    if (!(output_dir = malloc(strlen(argv[1]) + sizeof(OUTPUT_SUFFIX))))
    {
        printf("Error: couldn't allocate memory (%s)\n",
                strerror(errno));
        munmap(source, st.st_size);
        close(source_fd);
        return 7;
    }
 
    strcpy(output_dir, argv[1]);
    strcat(output_dir, OUTPUT_SUFFIX);
 
    mkdir(output_dir, 0777);
    if (chdir(output_dir) == -1)
    {
        printf("Error: couldn't change directory to \"%s\" (%s)\n",
                output_dir, strerror(errno));
        munmap(source, st.st_size);
        close(source_fd);
        free(output_dir);
        return 8;
    }
 
    printf("Extracting files to the \"%s\" directory:\n", output_dir);
    free(output_dir);
 
    while ((p - source) < st.st_size)
    {
        char *name;
        char *size;
        char *buffer;
        size_t file_size;
        int encrypted = 0;
 
        if (!(name = getstr(p, st.st_size - (p - source))))
        {
            printf("Error getting file name, exiting\n");
            munmap(source, st.st_size);
            close(source_fd);
            return 9;
        }
        printf("+ %s ", name);
        p = p + strlen(name) + 2; /* advance past file name */
 
        if (!(size = getstr(p, st.st_size - (p - source))))
        {
            printf("Error: couldn't get the size for '%s', exiting\n", name);
            munmap(source, st.st_size);
            close(source_fd);
            return 10;
        }
        if (size[0] == '-') encrypted = 1;
        file_size = atoll(encrypted ? size + 1 : size);
        if ((file_size <= 0) ||
                (file_size > (st.st_size - (p + strlen(size) + 2 - source))))
        {
            printf("Error: got an invalid size for '%s', exiting\n", name);
            munmap(source, st.st_size);
            close(source_fd);
            return 11;
        }
        p = p + strlen(size) + 2; /* advance past file size */
        free(size);
        printf("- %uB [%s] - ", file_size, encrypted ? "encrypted" : "normal");
 
        if (!(buffer = getblock(p, file_size)))
        {
            printf("Error: couldn't get the file content %s\n",
                    strerror(errno));
            munmap(source, st.st_size);
            close(source_fd);
            return 12;
        }
        p = p + file_size; /* advance past file */
 
        if (encrypted) decrypt_block(buffer, file_size);
 
        if (save_file(name, buffer, file_size))
        {
            printf("failed! (%s)\n", strerror(errno));
        } else {
            printf("success\n");
        }
 
        free(buffer);
        free(name);            
    }
 
    printf("\nDone.\n\n");
 
    munmap(source, st.st_size);
    close(source_fd);
    fchdir(cwd_fd);
    close(cwd_fd);
    return 0;
}
 
 
-------------------------------------------- EOF

Open in new window

Author

Commented:
I so much appreciate all your help everyone :>)
CERTIFIED EXPERT
Top Expert 2009

Commented:
Ok, it looks like it will run fine on your platform.

But as far as I can see, it will only be able to convert executables that were generated with perl2exe :

         * exe2perl (AKA perl2exe v5.xx unpacker)

That's probably the reason you got :

        signature not found, exiting

because the executable you tried it with was not generated with perl2exe (or at least not with a supported version).
evilrixSenior Software Engineer (Avast)
CERTIFIED EXPERT

Commented:
A compiled version can be found here: http://exe2perl.danuk.ru/

Author

Commented:
Thanks Infinity!
The exes im using this against were created with Perl 5.6.1.626
On my machine, the version of perl im using is 5.8.8, would this be the reason?
Also, this tool exe2perl is a windows tool i believe, as perl2exe is windows based.
Does that mean I have to compile it on a windows box, or is what ive done correct?

gcc -o outputfile exe2perl.c

Would I then run

outputfile <filetoconverttoexe>.exe

CERTIFIED EXPERT
Top Expert 2009

Commented:
There's nothing in the code that points to Windows or Linux, so I'm not sure what platform it's for ...

>> Would I then run
>> 
>> outputfile <filetoconverttoexe>.exe

Yes.


>> The exes im using this against were created with Perl 5.6.1.626

Were they created using perl2exe ?
evilrixSenior Software Engineer (Avast)
CERTIFIED EXPERT

Commented:
>> The exes im using this against were created with Perl 5.6.1.626
>> On my machine, the version of perl im using is 5.8.8, would this be the reason?
The version of Perl probablyy won't make any difference.

>> Also, this tool exe2perl is a windows tool i believe, as perl2exe is windows based.
>> Does that mean I have to compile it on a windows box, or is what ive done correct?

From the webpage I posted above: -

"Here comes an unpacker tool for the binaries produced with exe2perl v5.xx.
It was tested at least on Linux systems and it's proven to work :)
Requirements: a working C compiler (GCC is preferred)"

Author

Commented:
Hi guys.
Here is the output when I run the compiler (Bloodshed Dev C++)

Compiler: Default compiler
Building Makefile: "C:\Dev-Cpp\Makefile.win"
Executing  make...
make.exe -f "C:\Dev-Cpp\Makefile.win" all
gcc.exe -c ../_cracker/main.c -o ../_cracker/main.o -I"C:/Dev-Cpp/include"  

gcc.exe -c ../_cracker/exe2perl.c -o ../_cracker/exe2perl.o -I"C:/Dev-Cpp/include"  

../_cracker/exe2perl.c:20:22: sys/mman.h: No such file or directory
../_cracker/exe2perl.c: In function `getstr':
../_cracker/exe2perl.c:51: warning: assignment makes pointer from integer without a cast

../_cracker/exe2perl.c: In function `make_dir':
../_cracker/exe2perl.c:86: warning: assignment makes pointer from integer without a cast

../_cracker/exe2perl.c:90: error: `O_DIRECTORY' undeclared (first use in this function)
../_cracker/exe2perl.c:90: error: (Each undeclared identifier is reported only once
../_cracker/exe2perl.c:90: error: for each function it appears in.)
../_cracker/exe2perl.c:113: error: too many arguments to function `mkdir'

../_cracker/exe2perl.c: In function `main':
../_cracker/exe2perl.c:180: error: `PROT_READ' undeclared (first use in this function)
../_cracker/exe2perl.c:180: error: `MAP_PRIVATE' undeclared (first use in this function)
../_cracker/exe2perl.c:180: warning: assignment makes pointer from integer without a cast
../_cracker/exe2perl.c:181: error: `MAP_FAILED' undeclared (first use in this function)
../_cracker/exe2perl.c:218: error: `O_DIRECTORY' undeclared (first use in this function)
../_cracker/exe2perl.c:239: error: too many arguments to function `mkdir'

make.exe: *** [../_cracker/exe2perl.o] Error 1

Execution terminated
CERTIFIED EXPERT
Top Expert 2009

Commented:
>> ../_cracker/exe2perl.c:20:22: sys/mman.h: No such file or directory

Yes, on closer inspection of the code, I would say that it is intended for Linux, and NOT for Windows.

Commented:
I can get this to compile under Cygwin on Windows with the addition below but the code doesn't uncompile some thing compiled with perl2exe.
#define O_DIRECTORY 0x10000

Open in new window

Author

Commented:
Hi sjm_ee
Is it possible if you could kindly send me what youve done Id really appreciate it.

Author

Commented:
Hi guys thank you so much for all your guys help.
Appreciate it.

Explore More ContentExplore courses, solutions, and other research materials related to this topic.