Calling Conventions

There are different calling conventions for different operating systems or different bits of system
or you compile with the vs (or others)

  • Different conventions based on processor,OS,and Language Describe how are passed to functions
  • Describe how are returned from functions
  • Describe if the caller or callee clean the stack
  • Resonsible for function andprologueandepilogue

Windows x86 Calling Convention

Keyword Stack cleanup Parameter passing
__cdecl Caller Pushes parameters on the stack, in reverse order (right to left)
__clrcall n/a Load parameters onto CLR expression stack in order (left to right).
__stdcall Callee Pushes parameters on the stack, in reverse order (right to left)
__fastcall Callee Stored in registers, then pushed on stack
__thiscall Callee Pushed on stack; this pointer stored in ECX
__vectorcall Callee Stored in registers, then pushed on stack in reverse order (right to left)
  • All arguments are widened to 32 bits(DWORD)
  • Return value is widened to 32 bits(DWORD)
  • Return values up to 32 bits are returned to eax register
  • Return values of 64 bit size(QWORD) are returned in EDX:EAX(The main value is in the EDX Register)
  • Return Structures are returned by reference with a pointer in EAX
  • Registers ESI,EDI,EBX,and EBP are restored(non-volatile)
  • MSDN is your friend


  • Default calling convention for c and c++

  • Arguments are passed on the stack(pushed right-to-left)

  • Called is responsible for stack cleanup will (cdecl will clean the stack )

    • this is important when there are variadic functions,so function doesn’t

      worry about stack cleaning.

  • Supports varag(variadic)functions

Example code below:


then we can get follow code with ida


  • sub_401090 is the hello1 function
  • sub_401000 is the addingNumberVariadic function which is variadic
    • notice that caller clean the stack when the function return


The __stdcall calling convention is used to call Win32 API functions. The callee cleans the stack, so the compiler makes vararg functions __cdecl. Functions that use this calling convention require a function prototype. The __stdcall modifier is Microsoft-specific.

Element Implementation
Argument-passing order Right to left.
Argument-passing convention By value, unless a pointer or reference type is passed.
Stack-maintenance responsibility Called function pops its own arguments from the stack.
Name-decoration convention An underscore (_) is prefixed to the name. The name is followed by the at sign (@) followed by the number of bytes (in decimal) in the argument list. Therefore, the function declared as int func( int a, double b ) is decorated as follows: _func@12


The __fastcall calling convention specifies that arguments to functions are to be passed in registers, when possible. This calling convention only applies to the x86 architecture. The following list shows the implementation of this calling convention.

Element Implementation
Argument-passing order The first two DWORD or smaller arguments that are found in the argument list from left to right are passed in ECX and EDX registers; all other arguments are passed on the stack from right to left.
Stack-maintenance responsibility Called function pops the arguments from the stack.
Name-decoration convention At sign (@) is prefixed to names; an at sign followed by the number of bytes (in decimal) in the parameter list is suffixed to names.
Case-translation convention No case translation performed.


The Microsoft-specific __thiscall calling convention is used on C++ class member functions on the x86 architecture. It’s the default calling convention used by member functions that don’t use variable arguments (vararg functions).

Under __thiscall, the callee cleans the stack, which is impossible for vararg functions. Arguments are pushed on the stack from right to left. The this pointer is passed via register ECX, and not on the stack.

vararg member functions use the __cdecl calling convention. All function arguments are pushed on the stack, with the this pointer placed on the stack last.

Because this calling convention applies only to C++, it doesn’t have a C name decoration scheme.

When you define a non-static class member function out-of-line, specify the calling convention modifier only in the declaration. You don’t have to specify it again on the out-of-line definition. The compiler uses the calling convention specified during declaration at the point of definition.


The __vectorcall calling convention specifies that arguments to functions are to be passed in registers. __vectorcall uses more registers for arguments than __fastcall or the default x64 calling convention(rcx rdx r7 r8 [rsp+[size of arg]) use. The __vectorcall calling convention is only supported in native code on x86 and x64 processors that include Streaming SIMD Extensions 2 (SSE2) and above. Use __vectorcall to speed functions that pass several floating-point or SIMD vector arguments and perform operations that take advantage of the arguments loaded in registers. The following list shows the features that are common to the x86 and x64 implementations of __vectorcall. The differences are explained later in this article.

to be continue one day



OEP tricks


Why is the PE Entry Point Not the same as Main Understanding __security__init__cookieandscrt_common_main_seh

在第一次学习如何对 Windows 二进制文件进行逆向工程时,尤其是在使用调试器时,这是一个需要理解的重要概念。 当调试器在 PE 入口点上中断时,通常会让人感到困惑,只是为了找到一些与二进制文件的主要功能无关的代码。 此代码通常称为boilerplate代码,由 MSVC 编译器自动插入。 这对我们识别代码和方向有很大帮助。

MSVC console Application Entry point

The Entry Point on an MSVC console application servers two purples .

  • calls the __security__init_cookie function
  • jumps to the __scrt_common_main_sehthunk
    • The __scrt_common_main_seh thunk then performs some setup for the binary including some structured exception handler (SEH) setup and then calls main.


The purpose of this cookie is best described by MSDN

全局安全 cookie 用于在使用 /GS(缓冲区安全检查)编译的代码和使用异常处理的代码中进行缓冲区溢出保护。

在进入受溢出保护的函数时,cookie 被放入堆栈,而在退出时,堆栈上的值与全局 cookie 进行比较。 它们之间的任何差异都表明发生了缓冲区溢出并导致程序立即终止。

Normally, __security_init_cookie is called by the CRT when it’s initialized. If you bypass CRT initialization—for example, if you use /ENTRY to specify an entry-point—then you must call

__security_init_cookie yourself. If __security_init_cookie isn’t called, the global security cookie is set to a default value and buffer overrun protection is compromised. Because an attacker can exploit this default cookie value to defeat the buffer overrun checks, we recommend that you always call

__security_init_cookie when you define your own entry point.

we can use the opcode 48 89 5C 24 20 55 48 8B EC 48 83 EC 20 to find the __security_init_cookie


The call to __security_init_cookie must be made before any overrun-protected function is entered; otherwise a spurious buffer overrun will be detected. For more information, see C Runtime Error R6035.


Looking at this code without labels (for example in x64dbg) it can be confusing to identify where main is. Luckily MSVC console applications all have the same main function prototype.

*main(int argc, const char **argv, const char *envp)

This function prototype can be used to identify the call to main in __scrt_common_main_seh, simply by looking for the three arguments that are passed to main: argc, argv, envp.

  • In 64-bit binaries these arguments are compiled into a series of three mov instructions moving the arguments into the registers RCX, RDX, R8


    4C 8B C7                mov     r8, rdi         ; envp
    48 8B D3 mov rdx, rbx ; argv
    8B 08 mov ecx, [rax] ; argc
  • In 32-bit binaries these arguments are compiled into a series of three push instructions pushing the arguments onto the stack.


!!!!!!These patterns can be relied on to identify main. !!!!!!!



md5: e2bf42217a67e46433da8b6f4507219e


keylog Analysis


  • FindWindowA
  • ShowWindow
  • GetModuleHandleA
  • SetWindowHookExA
  • unhookWindowsHookEx


mining Virus Analysis

md5: eeb8f9ae60c73f84ff85bbeab9c0b6ee

filename: .systemd-private-nU9WagjQ8BenWPXt0ovE12uD8jBItv6

2021-09-02 hancitor



[Hancitor Continues to Push Cobalt Strike (](



Tweets with replies by Cryptolaemus (@Cryptolaemus1) / Twitter



1th Stage





>>> a = 'virtualallocexnuma'.upper() 
>>> h = 0
>>> for c in a:
... h = ror(h, 13)
... h += ord(c)
>>> h


如下图就是一个ror-13 hash算法得到的,因此恶意代码分析者无法轻易得知这是加载了哪一个函数。