注册 登录
编程论坛 C语言论坛

无法解析的外部符号 _WinMain@16

angie1123 发布于 2021-08-11 22:57, 1790 次点击
#include  <stdio.h>
    int main ()
{
    printf("%d\n", sizeof (char));
    return 0 ;
 }


错误    1    error LNK2019: 无法解析的外部符号 _WinMain@16,该符号在函数 ___tmainCRTStartup 中被引用    C:\Users\lsuvh\Documents\Visual Studio 2013\Projects\C languange lesson\C languange lesson\MSVCRTD.lib(crtexew.obj)    C languange lesson

请问为什么提示这个, 程序有什么问题吗?请教大佬
5 回复
#2
自由而无用2021-08-12 08:16
windows project : create win32
console project : create win32 console
#3
自由而无用2021-08-12 10:47
#include  <stdio.h>

int main(int argc, char *argv[])
{
    argv[5] = "sizeof char";
    argv[4] = "sizeof short";
    argv[3] = "sizeof int";
    argv[2] = "sizeof float";
    argv[1] = "sizeof double";
    argv[0] = "sizeof long int";
   
    char size[6] = {
        sizeof (long int),
        sizeof (double),
        sizeof (float),
        sizeof (int),
        sizeof (short),
        sizeof (char),
    };
   
    argc = 6;
    while (argc--)
        printf("%s: %c\n", argv[argc], 0x30 + size[argc]);
   
    return 0 ;
}

[此贴子已经被作者于2021-8-12 10:49编辑过]

#4
diycai2021-08-12 10:55
控制台应用程序你偏要用_WinMain程序入口,链接器表示很费解。
#5
自由而无用2021-08-12 12:59
#include <stdio.h>

int main(int argc, char *argv[])
{
    char tbl[6][12] = {
        {0x6c, 0x6f, 0x6e, 0x67, 0x20,
         0x69, 0x6e, 0x74, 0x20, 0x30 + sizeof (long int), 0},
        {0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x30 + sizeof (double), 0},
        {0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x30 + sizeof (float), 0},
        {0x69, 0x6e, 0x74, 0x20, 0x30 + sizeof (int), 0},
        {0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x30 + sizeof (short), 0},
        {0x63, 0x68, 0x61, 0x72, 0x20, 0x20, 0x30 + sizeof (char), 0}
    };

    argc = 6;
    while (argc--) {
        printf("sizeof %s\n", tbl[argc]);
    }
   
    return 0 ;
}

[此贴子已经被作者于2021-8-12 13:02编辑过]

#6
自由而无用2021-08-12 14:01
#include <stdio.h>

#define HIWORD(_w, _bit) _w << _bit
#define DIG(_n) _n + 0x30
#define _sizeof(T) ((size_t)((T*)0 + 1))

int main(int argc, char *argv[])
{
    int tbl[6][3] = {
        0x676e6f6c, 0x746e6920, HIWORD(DIG(_sizeof (long int)), 8) | 0x20,
        0x62756f64, HIWORD(DIG(_sizeof (double)), 24) | 0x20656c, 0,
        0x616f6c66, HIWORD(DIG(_sizeof (float)), 16) | 0x2074, 0,
        0x20746e69, 0x30 + _sizeof (int), 0,
        0x726f6873, HIWORD(DIG(_sizeof (short)), 16) | 0x2074, 0,
        0x72616863, HIWORD(DIG(_sizeof (char)), 16) | 0x2020, 0,
        };

    argc = 6;
    while (argc--) {
        printf("sizeof %s\n", (char *)tbl[argc]);
    }

    return 0 ;
}

[此贴子已经被作者于2021-8-12 20:00编辑过]

#7
diycai2021-08-12 15:58
回复 6楼 自由而无用
请问printf函数的调用约定是什么,  printf函数是如何获取参数的个数的, 这种方式可能出现什么漏洞?
#8
自由而无用2021-08-12 18:04
回复 7楼 diycai
#include <stdio.h>

#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"

int vebp, vesp;

//calling convention _cdecl glibc
int va_param(int nop, ...)
{
    __asm__ ("movl %esp, vesp");
    __asm__ ("movl %ebp, vebp");
        
    printf("esp = 0x%x\nebp = 0x%x\n", vesp, vebp);

    //non-optimized
    printf("0x%d", *(int *)(vesp+0x4));
    printf("0x%d", *(int *)(vesp+0x8));
    printf("0x%d", *(int *)(vesp+0x0C));
    printf("0x%d", *(int *)(vesp+0x10));
    printf("0x%d", *(int *)(vesp+0x14));
    //optimized
    //general register
   
    return 0;
}

int main(int argc, char *argv[])
{
    va_param(1,2,3,4,5);

    return 0;
}
#9
diycai2021-08-13 11:52
回复 8楼 自由而无用
参数个数问题怎么解决, 例如我传入 va_param(1,2,3,4,5,6);  6就无法显示,  我传入 va_param(1,2,3,4);  那就多显示了一个值。
#10
自由而无用2021-08-13 12:07
回复 9楼 diycai
calculate param push count, then esp - ebp / sizeof(int *)
#11
diycai2021-08-13 13:16
回复 10楼 自由而无用
问题是ebp仅仅是上一级调用函数入口的esp, 如果上一级调用函数中包含了临时变量,您这个结果就是错误的。
例如您的main()函数中,加入几个临时变量,您再看看结果对不对?
#12
自由而无用2021-08-13 14:08
回复 11楼 diycai
good question!
eg:

int va_param(int nop, ...)
{
    //push ebp
    //mov ebp, esp //va_param_esp
    //mov ecx,
    //mov eax, dword ptr[ebp + 0x04] //parm = 0x01
    //....
    //before return off-tunning -8, congratulations, you created a new calling convention!
    //__asm__("subl, $8, %esp");
    //ret
}

int main(int argc, char *argv)
{
    int a=1, b=2;
    //before call va_param tunning -8
    //__asm__ ("addl $8, %esp");
    va_param(1,2,3,4,5,6);
    return 0;
    //manual assembly code not debug
    //push ebp
    //mov ebp,esp    //main_esp
    //sub esp, 8
    //mov dword ptr[a], 1
    //mov dword ptr[b], 2
//from here calc length
    //push 6
    //...
    //push 1
//end of length //ebp - esp (- 8) how to tunning -8 manually?
    //call va_param
    //add esp, 8 //free local
    //ret

}
#13
自由而无用2021-08-13 14:11
one word only, use any way you can use to balance the stack
#14
diycai2021-08-13 15:11
回复 13楼 自由而无用

int va_param(int nop, ...)
{
    int counter;
    int i;

    __asm
    {
        push eax
        lea eax, counter
        mov [eax], edx
        pop eax
    }

    for (i=0; i<counter; i++)
    {
        printf("%d ", ((int *)&nop)[i]);
    }
    printf("\n");
   
    return 0;
}

int main(int argc, char *argv[])
{
    __asm
    {
        push edx
        mov edx, 4
    }
    va_param(1,2,3,4);
    __asm
    {
        pop edx
    }

    __asm
    {
        push edx
        mov edx, 5
    }
    va_param(1,2,3,4,5);
    __asm
    {
        pop edx
    }

    __asm
    {
        push edx
        mov edx, 6
    }
    va_param(1,2,3,4,5,6);
    __asm
    {
        pop edx
    }
    return 0;
}
1