2

I was wondering if it is possible to call printf for example without declaring the format array in the data segment. This question is regarding x86.

#include <stdio.h>

int main()
{
    __asm
    {
        push 1 ; number to print
        push 3710092110 ; format in ascii for %d\n
        call printf
        add esp, 8
    }

    return 0;
}

Ok so we need to push the address of the format instead of the format itself so something like this should be close enough right?

#include <stdio.h>

int main()
{
    __asm
    {
        push 3710092110 ; 3710092110 = format in ascii for %d\n
        push 1; argument to print
        lea edx, dword ptr[esp + 4]; get address of the format on stack
        push edx ; push the address of the format
        call printf
        add esp, 12
    }

    return 0;
}

Do you guys happen to have the time to demonstrate a working example? Can't find anything on the internet about it.

Mamma
  • 313
  • 2
  • 9
  • Yes, but (as I assume you know), not with that code. – Scott Hunter Nov 11 '15 at 12:08
  • 2
    It's possible, but you need to push a pointer to the format string, not the format string itself. – fuz Nov 11 '15 at 12:09
  • The C standard has no idea about "segments" or "sections". And you cannot just _declare_ a variable, but also have to _define_ it. – too honest for this site Nov 11 '15 at 12:13
  • 3
    How do you figure `3710092110` has *anything* to do with `%d\n`? – EOF Nov 11 '15 at 12:28
  • @EOF I didn't test it, but I figure 3710092110 is what you get when you convert contents of 4 byte char array "%d\n" to a 4 byte integer. – VLL Nov 11 '15 at 12:33
  • 1
    @Ville-ValtteriTiittanen: Well, maybe you *should* test it before talking to me. – EOF Nov 11 '15 at 12:37
  • 1
    @Mamma: And if you think `%d\n` is equal to the bytes `37`, `100`, `92` and `110`, you need to learn about both escape codes *and* null-termination. – EOF Nov 11 '15 at 12:42
  • @EOF you are correct as well, i used a bloody string to ascii converter and didn't think it would convert \n to the ascii code of \ and n and ofc i forgot the null terminator as well. thank you mate – Mamma Nov 11 '15 at 12:45

2 Answers2

3

The format string is passed by pushing its address on the stack. So you could put the string wherever you like, but still need to pass its address.

Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
3

Your second code snippet comes close but it still needs to use a different value for the contents of the format string %d\n.

The characters involved translate to %=37, d=100, \n=10 in decimal.
But it is far easier to work with hexadecimal: %=25h, d=64h, \n=0Ah Due to little endeanness we have to put the first character in the lowest byte of the dword to push on the stack. We leave the highest byte zero to have the necesary null termination.

%d\n  -->  000A6425h

Your code:

#include <stdio.h>

int main()
{
    __asm
    {
        push 000A6425h ;= format in ascii for %d\n
        push 1; argument to print
        lea edx, dword ptr[esp + 4]; get address of the format on stack
        push edx ; push the address of the format
        call printf
        add esp, 12
    }

    return 0;
}
Sep Roland
  • 33,889
  • 7
  • 43
  • 76