0
点赞
收藏
分享

微信扫一扫

使用 IDA 和 windbg 调试 LNK1123 转换到 COFF 期间失败:文件无效或损坏(中)

使用 IDA 和 windbg 调试 LNK1123 转换到 COFF 期间失败:文件无效或损坏(中)

原总结排错process monitorvsIDAwindbg调试rcCVT1101LNK1123

前言

在 ​​上一篇文章​​​ 中,我们总结了使用 ​​windbg​​ 和 ​​IDA​​ 找出 ​​cvtres.exe​

几个值得深究的问题

  1. 为什么链接的时候需要调用 cvtres.exe 呢?
    ​​​微软官方描述​​ 摘录如下:

You can specify a .res file when linking a program. The .res file is created by the resource compiler (RC). LINK automatically converts .res files to COFF. The CVTRES.exe tool must be in the same directory as LINK.exe or in a directory specified in the PATH environment variable.

  1. ​​stackoverflow​​ 上有一个更加详细的描述,摘录如下:

Input files must have the Common Object File Format (COFF) format. If an input file is not COFF, the linker automatically tries to convert 32-bit OMF objects to COFF, or runs CVTRES.EXE to convert resource files. This message indicates that the linker could not convert the file. This can also occur when using an incompatible version of CVTRES.EXE from another installation of Visual Studio, the Windows Development Kit, or .NET Framework.

  1. 有没有更好的设置条件断点的方式?目前的语法实在是太难用了。
    可以使用

​dx​

  1. 提供的语法来设置条件断点。先定义一个辅助函数

​@$get_wfs_open_file_param​

  1. 用来获取

​file​

dx @$get_wfs_open_file_param = (esp_value => ((wchar_t*)*((int*)esp_value+1)).ToDisplayString("sub"))

设置条件断点

bp /w "@$get_wfs_open_file_param(@esp).EndsWith(\"510.res\")" MSVCR120!_wfsopen

是不是比传统的方式好理解的多?如果不想定义辅助函数,可以直接像下面这样设置条件断点。

bp /w "((wchar_t*)*((int*)@esp+1)).ToDisplayString(\"sub\").EndsWith(\"510.res\")" MSVCR120!_wfsopen

有什么简单的办法可以查看 __piob

  1. 在前一篇文章中,只是通过逻辑推理确定了当尝试打开

​510.res​

  1. 时,

​__piob​

  1. 数组中的每个元素都被占用了。并没有实际查看其内容。其实,可以通过

​dx​

  1. 命令非常方便的查看想要查看的内容。比如,可以只查看那些可用的记录项(值为

​NULL​

  1. 或者不满足

​inuse()​

​str_locked()​

  1. 为了让代码更容易理解,定义了几个辅助变量及函数。

$$ 以下变量定义在 VC\crt\src\stdio.h 中
dx @$ioReadFlag = 0x1
dx @$ioWriteFlag = 0x2
dx @$ioRWFlag = 0x80
dx @$ioLockedFlag = 0x8000

$$ inuse() 和 str_locked() 定义在 VC\crt\src\file2.h 中
dx -r0 @$IsInUse = (f => f->_flag & (@$ioReadFlag | @$ioWriteFlag | @$ioRWFlag))
dx -r0 @$IsLocked = (f => f->_flag & @$ioLockedFlag)

$$ 使用自定义变量 my_piob 指向 __piob
dx -r0 @$my_piob = (FILE*[512])MSVCR120!__piob

$$ 找到所有可用的记录的数量
dx @$my_piob.Where(f => f == 0 || (@$IsInUse(f) && @$IsLocked(f) ) ).Count()

$$ 找到所有不可用的记录的数量
dx @$my_piob.Where(f => !(f == 0 || (@$IsInUse(f) && @$IsLocked(f) ) ) ).Count()

当打开 ​​510.res​

使用 IDA 和 windbg 调试 LNK1123 转换到 COFF 期间失败:文件无效或损坏(中)_条件断点

为什么在打开 510.res

  1. 猜测应该是已经打开了一些文件。为了验证这个猜测,再次调试。

​cvtres.exe​

  1. 中断到

​windbg​

  1. 后,执行

​x MSVCR120!__piob​

  1. 查看

​__piob​


可以看到此时 ​​__piob​​ 的地址是 ​​0x6250fe00​​ ,值是 ​​0​​。说明此时还没被赋值。通过 ​​ba w4 0x6250fe00​​ 设置内存写断点设置好后,执行 ​​g​​ 命令恢复运行。几乎立刻中断到 ​​windbg​

使用 IDA 和 windbg 调试 LNK1123 转换到 COFF 期间失败:文件无效或损坏(中)_赋值_02

可以看到 ​​__piob​​ 会在 ​​__initstdio()​​ 函数中被初始化。而且前 ​​_IOB_ENTRIES​​ 项(值为 ​​20​​)的值会被 ​​_iob​​ 中对应的值赋值。而 ​​_iob​

使用 IDA 和 windbg 调试 LNK1123 转换到 COFF 期间失败:文件无效或损坏(中)_赋值_03

所以,​​cvtres.exe​​ 最多只能通过 ​​_wfsopen()​​ 函数打开 ​​512-3 = 509​​ 个文件。也就是说,只能打开 ​​1.res ~ 509.res​​,打开 ​​510.res​

More

还有一个小问题没解决 —— 为什么设置 ​​PATH​​ 环境变量后,直接通过文件名启动程序,​​windbg​

总结

  • 命令行程序默认会打开三个文件

​stdin、stdout、stderror​

  • 。所以,

​crt​

  • 默认能同时打开的文件数是

​509​​​​dx​

参考资料

​​https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/setting-a-conditional-breakpoint​​

​​https://docs.microsoft.com/en-us/cpp/build/reference/dot-res-files-as-linker-input?view=msvc-170​​

​​https://stackoverflow.com/questions/61581826/visual-studio-2019-cvt1101-lnk1123-fatal-error​​

​vs2013​​ 自带的 ​​crt​

欢迎各位小伙伴指出不足,提出建议!感谢关注我的博客:)

作 者:​​编程难​​

码云博客:​​https://bianchengnan.gitee.io​​

github博客:​​https://bianchengnan.github.io​​

版权所有,转载请保留原文链接:)



举报

相关推荐

0 条评论