详细信息:我正在查看使用以下(非标准)调用约定的x86可执行文件。
调用方在堆栈上为可能的多个返回值创建空间,即从
4*return_count
中减去ESP
。为局部变量创建一个堆栈框架callee可以工作
callee将
ESP
恢复为与步骤3之前的相同callee将返回值存储在其参数下方的堆栈中br />
现在,调用者将返回值和参数保留在本地堆栈框架中,后者位于前者之上,并进行清理。这是GoLang 1.10可执行文件,但是我正在描述我在这里看到的调用约定,对此我不知道任何参考。如果已知Windows编译的可执行文件中有关GoLang调用约定的信息;我也会对此非常感兴趣。
但是,更重要的是,我正在寻找一种方法来使IDA正确理解此调用约定。例如,考虑以下代码:
test proc near ; test receives two arguments
sub esp, 18h ; create stack frame
mov eax, [esp+1Ch] ; argument 1 to test:
mov [esp], eax ; moved to top of stack frame
mov eax, [esp+20h] ; argument 2 to test:
mov [esp+4], eax ; moved second to top of stack frame
call sub1 ; call sub1(test_arg_1, test_arg_2)
mov eax, [esp+14h] ; retrieve return_value_1
mov ecx, [esp+10h] ; retrieve return_value_2
mov [esp], ecx
mov [esp+4], eax
call sub2 ; call sub2(return_value_1, return_value_2)
movzx eax, byte ptr [esp+8] ; retrieve single return value
xor eax, 1 ; negate result
mov [esp+24h], al ; store result below arguments to test
add esp, 18h ; close stack frame
retn ; return
我试图给
sub1
提供更多参数:int __cdecl sub1(int, int, int, int, int, int)
但是不幸的是,反编译后的代码并未反映出此函数的最后两个“参数”实际上是返回值,这些值正传递给
sub2
:int __cdecl test(int a1, int a2)
{
int v2; // ST10_4
int v3; // ST14_4
unsigned __int8 v4; // ST08_1
int esp_08; // [esp+8h] [ebp-10h]
int esp_0C; // [esp+Ch] [ebp-Ch]
int esp_10; // [esp+10h] [ebp-8h]
int esp_14; // [esp+14h] [ebp-4h]
void *retaddr; // [esp+18h] [ebp+0h]
sub1(a1, a2, esp_08, esp_0C, esp_10, esp_14);
sub2(v2, v3);
return v4 ^ 1;
}
为了尝试使用这种高级调用约定语法,我还创建了一个包含两个32位整数字段的结构,并按如下所示声明了
sub1
:struc_1 __usercall sub1@<0:^8.4,4:^12.4>(int, int)
我尝试过此变量的几种变体,不同的偏移量,也仅返回本机类型,但是IDA 7.1始终崩溃,并显示以下消息:糟糕!发生内部错误1004。无法进一步的工作,并且IDA将关闭。 br再现MWE
要产生上面的示例,可以使用以下
test.go
源文件:如下所示(禁用优化很重要):package main
import "os"
func sub2(x int, y int) bool { return x == y }
func sub1(x int, y int) (int, int) { return y,x }
func test(x int, y int) bool { return ! sub2(sub1(x,y)) }
func main() {
test(1,2)
os.Exit(0)
}
在IDA中,测试功能应自动重命名为
main_test
。
评论
由于您似乎拥有最新的IDA,并且崩溃了,因此您可以与支持人员联系以解决此问题。一个好主意,谢谢。我有点害怕错误地使用语法,但是我会问他们有关问题。
如果这样声明,它会起作用吗? int __cdecl test(int a1,int a2,int * return1,int * return2)
亲爱的@AntonKukoba,感谢您的提议,可惜它不起作用。在这种情况下,它只是认为参数是int指针而不是int,没有其他改变。
你能给我一个样品,我想尝试