0x5929
0x5929

Reputation: 572

C - how does (*(void (*)()) code); run in a C program without any invocation

To run arbitrary assembled hex instructions within a C program usually requires casting the data as a function pointer and then invoking such pointer.

Common Usage

int main(){    
    void (*ret)() = (void(*)())code;
    ret();
    return 0;
}

However I have also run across another way of achieving the same task as such

Case in Question

int main() {
    (*(void (*)()) code);
    return 0;
}

Can someone help explain:

  1. The difference between the two cases
  2. How come the second case works without any invocation

The problem arises when it is difficult to track the hex instruction code in a debugger such as GDB without an actual invocation of the hex code in script of the second case.

Edit

The program tested were compiled with gcc, and with options: -fno-stack-protector -z exexcstack

machine tested and gcc version :

gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04)

Upvotes: 0

Views: 675

Answers (1)

Petr Skocik
Petr Skocik

Reputation: 60163

The second piece of code won't work. The unused deref is a no-op. It's equivalent to an empty function. If you want to avoid the variable use ((void (*)())code)().

Example:

extern char *code;
void run()
{
    void (*ret)() = (void(*)())code;
    ret();
}
void run0()
{
    (*(void (*)()) code);
}
void empty()
{
}
void novar()
{
    ((void (*)())code)();
}

Disassembly (x86_64) of Example:

ex.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <run>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 83 ec 10             sub    $0x10,%rsp
   8:   48 8b 05 00 00 00 00    mov    0x0(%rip),%rax        # f <run+0xf>
   f:   48 89 45 f8             mov    %rax,-0x8(%rbp)
  13:   48 8b 55 f8             mov    -0x8(%rbp),%rdx
  17:   b8 00 00 00 00          mov    $0x0,%eax
  1c:   ff d2                   callq  *%rdx
  1e:   90                      nop
  1f:   c9                      leaveq 
  20:   c3                      retq   

0000000000000021 <run0>:
  21:   55                      push   %rbp
  22:   48 89 e5                mov    %rsp,%rbp
  25:   90                      nop
  26:   5d                      pop    %rbp
  27:   c3                      retq   

0000000000000028 <empty>:
  28:   55                      push   %rbp
  29:   48 89 e5                mov    %rsp,%rbp
  2c:   90                      nop
  2d:   5d                      pop    %rbp
  2e:   c3                      retq   

000000000000002f <novar>:
  2f:   55                      push   %rbp
  30:   48 89 e5                mov    %rsp,%rbp
  33:   48 8b 05 00 00 00 00    mov    0x0(%rip),%rax        # 3a <novar+0xb>
  3a:   48 89 c2                mov    %rax,%rdx
  3d:   b8 00 00 00 00          mov    $0x0,%eax
  42:   ff d2                   callq  *%rdx
  44:   90                      nop
  45:   5d                      pop    %rbp
  46:   c3                      retq   

https://gcc.godbolt.org/z/lEo5ga

Upvotes: 4

Related Questions