I'm trying to do CMU's binary bomb as an independent project to learn some x86 Assembly and reverse engineering. (It's not an auto-graded version tied to a class.)
I downloaded bomb.tar from http://csapp.cs.cmu.edu/public/labs.html.
From CMU's lab description:
A "binary bomb" is a program provided to students as an object code
file. When run, it prompts the user to type in 6 different strings. If
any of these is incorrect, the bomb "explodes," printing an error
message and logging the event on a grading server. Students must
"defuse" their own unique bomb by disassembling and reverse
engineering the program to determine what the 6 strings should be. The
lab teaches students to understand assembly language, and also forces
them to learn how to use a debugger. It's also great fun. A legendary
lab among the CMU undergrads.
Here's a Linux/IA32 binary bomb that you can try out for yourself. The
feature that notifies the grading server has been disabled, so feel
free to explode this bomb with impunity.
After saving it into an appropriate folder I ran this command in the Terminal:
tar xvf bomb.tar
It did extract a file called bomb (no file extension), but I thought it would also give me bomb.c, which would also be helpful for reference.
I can't get "bomb" to run. Here's what I've tried:
bomb
bomb: command not found
./bomb
bash: ./bomb: No such file or directory
While I realize solving it requires stepping through it in gdb, I can't even run it in BASH and blow myself up with wrong answers yet! A little help would be fantastic.
As the other answers have suggested, this appears to a CPU architecture compatibility issue. I was able to resolve this on Ubuntu 15.04 64-bit by installing the packages located at AskUbuntu.com How to run 32-bit programs on a 64-bit system [duplicate]
Specifically, the following command helped.
sudo apt-get install lib32z1 lib32ncurses5 lib32bz2-1.0
Since Fabio A. Correa ran file on the bomb and found out that it was a 32-bit LSB executable, it seems that is is caused by some missing LSB scripts which should be loaded at startup.
Simply running sudo apt-get install lsb-core will fix this. After doing so, ldd bomb will also work.
Update:
Further ldd (after getting the LSB things ready) shows that it is actually caused by some inexist libc.so.6 => /lib32/libc.so.6, which is the libc of the i386 architecture. You can try installing the libc6-i386 package directly instead.
After that, you can run disassemble func_name in your gdb directly. With all the symbols preserved, you can see the names of the functions directly. strings might help you too.
Btw, this question should be placed in Unix&Linux, I guess.
file bomb informs:
ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.0.0, not stripped
You should be able to run it on bash by typing:
tar xvf bomb.tar
chmod +x bomb
./bomb
It worked in my 64-bit Kubuntu 14.04.
Related
I'm attempting to compile a relatively simple Fortran executable so that it can be passed around to other Windows users that don't have Cygwin (or something of the sort) installed, however, I'm unable to get the executable to operate as a standalone. I've tried gfortran -static file.f and gfortran -static-libgfortran file.f, however other users always encounter this error:
The program can’t start because cygwin1.dll is missing from your computer. Try reinstalling the program to fix this problem.
From what I've read online (e.g. here), the -static option should be sufficient. I have verified that running the executable from my machine (DOS prompt) does work.
I have gcc (gfortran) version 4.7.3. I should also point out this is my first attempt at compiling portable Fortran.
Update
After realizing that this isn't a gfortran-specific issue (thanks to replies here), searches led me to related posts here and here
This is partially explained in the Cygwin FAQ. The solution is to install the mingw64-i686-gcc-fortran package with its dependencies, and cross-compile your code with i686-w64-mingw32-gfortran -static.
Just package the cygwin1.dll along with your binary file (both in the same folder) then it will run just fine.
I write some programs on linux with C
I want to run these programs on many remote computers, which are installed with fedora or ubuntu
I compiled the program with gcc on local machine, however the excutable file is not workable on remote machines.
for example: I use
gcc -o udp_server udp_server.c
on local machine to get a excutable binary file udp_server and then I copy it to a remote machine and run it there, the error is:
-bash: ./udp_server: /lib64/ld-linux-x86-64.so.2: bad ELF interpreter: No such file or directory
the local machine: fedora
Fedora release 16 (Verne)
Kernel \r on an \m (\l)
3.6.10-2.fc16.x86_64 GNU/Linux
the remote machine:
Fedora release 12 (Constantine)
Kernel \r on an \m (\l)
2.6.32-36.onelab.x86_64 GNU/Linux
on these remote machines, there are no gcc compiler
so I hope I can make some excutable files so that they can be executed on those remote machines
so what kind of excutable files should I make, and how to make them?
any recommenation tools or procedures?
thanks!
To run a program written in C, you must first compile it to produce an executable file. On Linux, the C compiler is typically the "Gnu C Compiler", or gcc.
If you compile a C program on Linux, it should usually run on any other Linux computer. However, a few conditions must be met for this to work:
A compiled executable is compiled for a specific processor architecture. For example, if you compile for x86-x64, the program will not run on x86 or PowerPC.
If the program uses shared libraries, these must be installed on the target system. The C library, "libc" is installed everywhere, other libraries may not be.
As to how to compile: For a simple program, you can invoke gcc directly. For more complex programs, some build tool is advisable. There are many to choose from; two popular choices are GNU make (the traditional solution), and CMake.
To distribute the program: If it is only a single executable, you can just copy this executable around. If the program consists of multiple files (images, data files, etc.), you should package it as a software package. This allows users to install it using a package manager such as RPM or dpkg. How to do this is explained in various packaging guides for the different Linux distributions.
Finally, a piece of advice: You seem to know very little about software development in general and in C in particular. Consider reading some tutorial on programmin in C - this will answer these (and many other) questions. There are countless books and online tutorials - I can recommend "The C book", by gbdirect.
The issue you see is you are missing a dynamic library on the target machine. To see which libraries you need you need to use "ldd" program. Example (I just execute it against standard program "test" which is in every single linux distribution):
$ ldd /usr/bin/test
linux-vdso.so.1 => (0x00007fff5fdfe000)
libc.so.6 => /lib64/libc.so.6 (0x00000032d0600000)
/lib64/ld-linux-x86-64.so.2 (0x00000032cfe00000)
On Fedora and RHEL you can find which RPM package you want to install using the following command
$ rpm -q --whatprovides /lib64/ld-linux-x86-64.so.2
glibc-2.16-28.fc18.x86_64
And then you need to install it:
$ yum -y install glibc-2.16-28.fc18.x86_64
I dont use Ubuntu / Debian, not sure how to do this. Please note that on 32bit systems libraries for 64bits are not avaiable, but on 64bit systems these libraries have usualla i686 tag and are installable.
Usually, you can execute your program on different machines as long as you keep the architecture. E.g. you cannot execute 64bit program on a 32bit machine, and also vice versa (you can workaround this by installing 32bit libs but thats maybe too difficult).
If you have different distributions, or different versions of same linux distribution, this might be problem - you need to make sure you have all the dependencies in the same major versions.
Or you can link libraries statically which is not usual in the linux world at all, but you can do this. Learn how to use GCC and then you will find out how to do that.
I am using a software for graph mining.
I have got the binary of that software in 2 folders for Linux mode and SunOs mode but don't have the source.
I am able to run the binary in Linux machine.
But when I want to run the binary in a Mac machine I am getting "command not found" for both the Linux and SunOs folders' binaries.
Could someone suggest if it can be able to run this in a MAC machine by any means like using a Linux shell or something
Gaurav
EDIT:I am getting "cannot execute binary" error when I set chmod to "u+x"
You'll need to recompile it for OS X or use a VM.
A command not found just means you're not executing it right, make sure it's chmod u+x and it's either on your PATH, or you specify the path explicitly.
If you use the file command you will see the difference, on the linux executable you'll have something like:
ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically
linked, for GNU/Linux 2.6.15, not stripped
and something like this for OS X executables:
command: Mach-O universal binary with 2 architectures command (for
architecture x86_64): Mach-O 64-bit executable x86_64 command (for
architecture i386): Mach-O executable i386
Operating systems generally don't support executing object code any extra formats... If Mac osx decended from solaris or Linux, then there could be some incentive for legacy support. But just assume everything to be binarily incomparable if it was compiled for a different arch and platform. There are a few places where you inherit backwards compatibility, running 32 but code on 64 bit oses... Or ppc code support on intel macs, but I suspect that both of those, especially the latter were non trivial engineering tasks.
Here are your options...
Get the source and compile on the Mac, if it compiles on Linux and solaris good chance it will compile and run ok on Mac.
Run through an emulator or boot camp
I am running red had linux 7.3 (old, I know), and for the past few months I've been learning assembly programming, writing small programs and compiling with nasm. For months, things have been going fine, and now for some unknown reason, I cannot execute any programs that I compile.
nasm file.s //used to work just fine, then I'd execute ./file
now, when I run ./file, first I get "permission denied", which never used to happen before. then, once i chmod +777 file, I get "cannot execute binary file".
I have NO IDEA why this is happening, but it is extremely frustrating since NOTHING I compile will run anymore.
Logging in as root doesn't change anything.
All suggestions are welcome, THANK YOU!!
nasm does not produce an executable, but just an object file (like gcc -c would). You still need to run the linker on it.
N.B.: “0777 is almost always wrong.”
Run the file command on your binaries and make sure they're identified correctly as executables.
Also try the ldd command. It will very likely fail for the exact same reason, but it's worth a shot.
This can happen if the file system you operate on is mounted with the noexec option. You could check that by doing mount | grep noexec and see if your current working directory suffers from that.
"Cannot execute binary file" is the strerror(3) message for the error code ENOEXEC. That has a very specific meaning: (quoting the manpage for execve(2))
[ENOEXEC] The new process file has the appropriate access
permission, but has an unrecognized format
(e.g., an invalid magic number in its header).
So what that means is, your nasm invocation is not producing an executable, but rather something else. As John Kugelman suggests, the file command will tell you what it is (user502515 is very likely to be right that it's an unlinked object file, but I have never used nasm myself so I don't know).
BTW, you'll do yourself a favor if you learn GAS/"AT&T" assembly syntax now, rather than when you need to rewrite your assembly code for an architecture that doesn't do Intel bizarro-world syntax. And I do hope you're using assembly only for inner-loop subroutines that actually need to be hand-optimized.
This just happened to me. After running
file <executable name>
it output <file name> ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
And the problem was that I was trying to run a 64 bit app on a 32 bit machine!
You may try looking into /var/log for some change in the system from this start to happen.
Good morning,
on a 64bit RedHat box we have to compile and run a 32bit application. Meanwhile I managed to compile the gcc version needed (4.0.3) and all required runtime libraries in 32bit and have set the LD_LIBRARY_PATH to point to the 32bit versions, but now during the remaining build process, a small java program needs to be executed which is installed in /usr/bin as a 64bit program, which now finds the 32bit version of libgcc_s.so first.
In general, if I set the LD_LIBRARY_PATH to the 32bit versions, I break the 64bit programs and vice versa.
How it this supposed to work at all? I am certain I am not the first person with this problem at hand. How is it solved usually?
Regards,
Stefan
Add both the 32-bit and 64-bit directories to the LD_LIBRARY_PATH.
If you do this, then the ld.so for 32-bit or 64-bit will use the correct libraries.
e.g. A 32-bit test app "test32" and 64-bit test app "test", with a locally-installed copy of a (newer version of) gcc and binutils in a user homedir, to avoid clobbering the system-wide install of gcc:
=> export LD_LIBRARY_PATH=/home/user1/pub/gcc+binutils/lib:/home/user1/pub/gcc+binutils/lib64
=> ldd ./test32
libstdc++.so.6 => /home/user1/pub/gcc+binutils/lib/libstdc++.so.6 (0x00111000)
libgcc_s.so.1 => /home/user1/pub/gcc+binutils/lib/libgcc_s.so.1 (0x00221000)
=> ldd ./test
libstdc++.so.6 => /home/user1/pub/gcc+binutils/lib64/libstdc++.so.6 (0x00007ffff7cfc000)
libgcc_s.so.1 => /home/user1/pub/gcc+binutils/lib64/libgcc_s.so.1 (0x00007ffff7ad2000)
(Less interesting library paths removed)
This shows that the loaders know to ignore the libraries of the wrong architecture, at least on this Scientific Linux 6.3 (RHEL-derived) system. I would expect other distros to work similarly, but haven't tested this.
This may have only started being the case more recently than your (unspecified) distro version, however.
On Solaris one can use LD_LIBRARY32_PATH and LD_LIBRARY64_PATH, but that isn't supported on Linux.
In general, you should just never need to set LD_LIBRARY_PATH at all in the first place:
either install needed libraries into
/usr/lib32 or /usr/lib64 as
appropriate, or
build your 32-bit application with -Wl,-rpath=/path/to/32-bit/libs
As a workaround, wrap the Java call in a small shell script which unsets LD_LIBRARY_PATH and then calls the executable. Alternatively, this might also work:
LD_LIBRARY_PATH= java...
Note the space between "=" and the name of the executable.
Just set LD_LIBRARY_PATH to both paths (use colons to delimit). The linker will ignore the libraries that it cannot read.
I have faced this exact same problem when remastering a 32bit tinycore64 system running a 64bit kernel.
After much searching, I have discovered why these comments would make sense to both of them.
"That would be nice, but - at least in my environment - it did not
appear to work. The loader did complain; it did not simply skip the
libraries that do not match the bit-ness. Sadly!" - struppi
"This is very strange, could you describe how things failed? Also,
perhaps post the output of ldd?" - Adam Goode
And why this comment might appear to be true but is actually incorrect.
The linker will ignore the libraries that it cannot read.
This link shed's some light on it.
http://www.markusbe.com/2009/09/about-running-32-bit-programs-on-64-bit-ubuntu-and-shared-libraries/
And more to the point, you will find the ld.so manpage enlightening.
It turns out the path name can make a difference in what the runtime linker ld.so chooses as the library to load. On my 64bit linux system I have a range of odd directory names in addition to the standard ones. e.g. /lib/x86_64-linux-gnu. I actually thought I'd experiment by moving the libraries in that path to /lib64. When I did that, guess what happened? suddenly my 64bit app (brctl in this case) didn't work and complained with "Wrong ELF class". Hello... now we're onto something.
Now I'm not 100% certain but the key seems to be related to rpath token expansion.
I suspect the ${PLATFORM} expansion may have something to do with it. And the name x86_64 must be part of that.
In any case, I found when I put my 64-bit libraries in library paths named
x86_64-linux-gnu as apposed to just lib64, then they were preferred over the 32bit ones and things worked.
In your case, you probably want to do something very similar for 32bit libraries on 64. Try i386-linux-gnu.
So in my case where I am installing 64bit shared libraries onto a 32bit userland, I created the following paths:
mkdir /lib/x86_64-linux-gnu/
mkdir /usr/lib/x86_64-linux-gnu/
ln -s /lib/x86_64-linux-gnu /lib64
ln -s /usr/lib/x86_64-linux-gnu /usr/lib64
Add your 64bit libraries to the 64bit paths and 32bit libraries to the 32bit /lib & /usr/lib paths only.
Then add the 64bit specific paths to ld.so.conf and update your cache with ldconfig
Now your 32-bit & 64-bit applications will run seamlessly.