参考:
1、https://github.com/ShenXiaolong1976/sourceIndex_forGit
篇(二)提到,VS SDK自带的Debugger并不支持git,而git已经逐渐取代svn成为最流行的版本控制工具,但VS2019或SDK2004仍旧没有gitindex。可能原因:
- git是分布式版本系统,源码服务器地址设置为本地的话,不好固定;
- 设置为远端的话,不同的git服务器源码获取路径不尽相同,如gitlab、gitee、github、gogs等都不一样,导致没法统一。如果Debugger支持gitindex,可能也会是gitlabIndex、githubIndex之类的。
那么,如果我们将需求降低,仅仅是为了分析dump,使用本地工作目录也未尝不可。而且,已经有人实现了这样的GitIndex——sourceIndex_forGit
(见参考1),下面根据前人贡献分析并实操。
0x00 sourceIndex_forGit
首先看,sourceIndex_forGit
是如何使用的,参考工程README.md
。
- 从github下载并解压至文件夹,如“C:\GitIndex”
- 将“C:\GitIndex”添加至PATH环境变量
1、源文件索引
命令:gitIndex.cmd <sourceCodeDir> <pdbFilesDirPath>
示例:
1 | gitIndex.cmd "D:\VC++ Work\DumpDemo" "D:\VC++ Work\DumpDemo\Release\"
|
注意:源码路径最后不要加\
!
接下来,使用symstore
命令将符号添加至符号服务器
1 | symstore add / f "D:\VC++ Work\DumpDemo\Release\*.pdb" / s "D:\sym" / t "DempDemo" / v "1.0.0.0" / o
|
2、dump分析
首先打开C:\GitIndex
下的gitFetchFile.cmd
,设置localGitRepo
1 | set localGitRepo = D:\VC + + Work\DumpDemo
|
打开windbg,设置源码保存路径D:\src,符号路径:D:\sym,打开Dump文件,输入!analyze -v
便可以自动下载符号和源码了。
0x01 GitIndex
下面讨论如果不看sourceIndex_forGit
,如何自己实现一个GitIndex
。
1、GitIndex要实现什么
由前两篇,我们要实现源文件索引及符号服务器添加,利于dump的“自动化”分析,后者使用symstore
命令即可完成,前者才是讨论的重点。
- 在pdb文件中添加什么信息
- 用什么方式从源码路径提取我们需要的版本文件
2、SVN源码获取方式
由SVN篇,我们再分析一下svnIndex到底向pdb文件中添加了什么。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | SRCSRV: ini - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
VERSION = 1
INDEXVERSION = 2
VERCTRL = Subversion
DATETIME = Tue Sep 8 15 : 32 : 07 2020
SRCSRV: variables - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SVN_EXTRACT_TARGET = % targ % \ % fnbksl % ( % var3 % )\ % var4 % \ % fnfile % ( % var1 % )
SVN_EXTRACT_CMD = cmd / c svn.exe cat "%var2%%var3%@%var4%" - - non - interactive > "%svn_extract_target%"
SRCSRVTRG = % SVN_extract_target %
SRCSRVCMD = % SVN_extract_cmd %
SRCSRV: source files - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
d:\work\dumpdemo\dumpdemo\stdafx.h * https: / / nemo - pc / * svn / Work / DumpDemo / DumpDemo / stdafx.h * 38
d:\work\dumpdemo\dumpdemo\dump.h * https: / / nemo - pc / * svn / Work / DumpDemo / DumpDemo / dump.h * 38
d:\work\dumpdemo\dumpdemo\dumpdemo.cpp * https: / / nemo - pc / * svn / Work / DumpDemo / DumpDemo / DumpDemo.cpp * 38
d:\work\dumpdemo\dumpdemo\targetver.h * https: / / nemo - pc / * svn / Work / DumpDemo / DumpDemo / targetver.h * 38
d:\work\dumpdemo\dumpdemo\stdafx.cpp * https: / / nemo - pc / * svn / Work / DumpDemo / DumpDemo / stdafx.cpp * 38
SRCSRV: end - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
重点在第7、8行
1 2 | SVN_EXTRACT_TARGET = % targ % \ % fnbksl % ( % var3 % )\ % var4 % \ % fnfile % ( % var1 % )
SVN_EXTRACT_CMD = cmd / c svn.exe cat "%var2%%var3%@%var4%" - - non - interactive > "%svn_extract_target%"
|
SVN_EXTRACT_TARGET
:从源码服务器下载对应的文件后的保存位置,暂不讨论;
SVN_EXTRACT_CMD
:
- 怎么从源码服务器下载对应源码:
cmd /c svn.exe cat "%var2%%var3%@%var4%" --non-interactive
- 保存到哪儿:
> "%svn_extract_target%"
可以看出,这里的var2
、var3
、var4
便是SRCSRV: source files ---------------------------------------
和SRCSRV: end ------------------------------------------------
中间每行使用星号隔开的字符串。实际执行时(srctool
的输出)
1 | cmd / c svn.exe cat "https://nemo-pc/svn/Work/DumpDemo/DumpDemo/stdafx.h@38" - - non - interactive > "C:\Windows\system32\svn\Work\DumpDemo\DumpDemo\stdafx.h\38\stdafx.h"
|
SVN_EXTRACT_CMD
这个是我们重点讨论并实现的。
3、GIT源码获取方式
首先看,git如何获取对应版本的源码文件。
在sourceIndex_forGit
中可以找到,获取源码方式(第63、64行)
1 2 | @echo GIT_EXTRACT_TARGET = % % targ % % \gitsrc\ % % fnbksl % % ^( % % var3 % % ^)\ % % var2 % % \ % % fnfile % % ^( % % var1 % % ^)
@echo GIT_EXTRACT_CMD = cmd / c gitFetchFile.cmd "%%var2%%:%%var3%%" "%%GIT_EXTRACT_TARGET%%"
|
即,cmd /c gitFetchFile.cmd "%%var2%%:%%var3%%" "%%GIT_EXTRACT_TARGET%%"
使用批处理,将两个参数传入,实现了git源码的获取。
打开gitFetchFile.cmd
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | ::@echo off
::my local git repo setting.
set localGitRepo = D:\VC + + Work\testDump
if not defined localGitRepo (
echo localGitRepo environment is not defined.
echo define localGitRepo environment variable point to local git repo.
echo e.g. set localGitRepo = D:\sourceCode\jabberGit129
goto :eof
)
if not exist "%~dp2" md "%~dp2"
git.exe - C "%localGitRepo%" show "%~1" > "%~fs2"
echo type "%~fs2"
type "%~fs2"
|
最后调用的是:git.exe -C "%localGitRepo%" show "%~1" > "%~fs2"
即:git.exe -C 源码目录 show 版本:文件名
测试下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | PS D:\> git - C "D:/VC++ Work/DumpDemo" log
commit 1fb32b03b9c6650b68a09737a50b2fe05bf4b98f (HEAD - > master)
……
commit 3f7a2efaf30840782475fab9841bdbc66397da39
……
commit 37841d6912ba17ecb2ede0cd93eb98ba2b5d4d6a
……
commit e66724029f6a8e2017ef9bdc7d97bebc39b395e6
……
commit 00d50d5368376dcea4e1eff99835d4163642cb4c
PS D:\> git - C "D:/VC++ Work/DumpDemo" show "37841d69:DumpDemo/DumpDemo.cpp" / / DumpDemo.cpp : <B6><A8><D2><E5><BF><D8><D6><C6><CC><A8><D3><A6><D3><C3><B3><CC><D0><F2><B5><C4><C8><EB><BF><DA><B5>
<E3><A1><A3>
/ /
int _tmain( int argc, _TCHAR * argv[])
{
::SetUnhandledExceptionFilter(UnhandledExceptionFilterEx);
char * buf = NULL;
buf = (char * )malloc( 10 );
if (buf)
{
memcpy(buf, "123456789" , sizeof( "123456789" ));
free(buf);
buf = NULL;
}
memcpy(buf, "123456789" , sizeof( "123456789" ));
return 0 ;
}
|
可以说,搞清了git命令是如何提取对应版本文件的,设计自己的GitIndex便有了大概的思路。
0x02 GitIndex设计
- 初始化
srcstr
- 枚举pdb文件
- 将每个pdb文件中的源码信息提取出来,
- 将源码信息和源码路径比较,如果是源码文件夹内的,获取git版本信息,字符串拼接至
srcstr
- 将
srcstr
回写入pdb文件中
- 继续处理下一个pdb文件
- 所有pdb文件处理完毕,调用
symstore
将pdb文件添加至符号服务器
gitIndex.cmd
通过批处理方式完成了以上步骤(除了最后一步),附件是使用C++完成的一个GitIndex.exe
,目的是充分理解这个过程,使用方式和gitIndex.cmd
一致。
0x03 其他Web git服务器的源码拉取方式
如果使用了git服务器,可以直接将服务器地址写入pdb文件中,使用curl下载文件来实现源码的拉取。下面是一些主流git服务器的源码拉取地址。
1、github
github源文件拉取地址格式:
示例:https://raw.githubusercontent.com/ecsousa/GitIndexer/fd3c994b6312708d6715a341676da40016d5e3ce/Package/tools/install.ps1
格式:https://raw.githubusercontent.com/%account%/%Project%/%CommitID%/%Path%/%File%
2、gogs
gogs源文件拉取地址格式:
示例:http://gogs.mygit.com/MyGroup/MyProject/raw/d91de318c40b8a95a64169b5824e5cf441a53e53/Dll/Dll.h
格式:http://地址/%Project%/raw/%CommitID%/%Path%/%File%
3、gitlab
gitlab源文件地址格式:
示例:http://gitlab.mygit.cn/myaccout/MyProject/raw/cb736ff9a6341c876c4358c5e47d0cdad250842d/Dll/Dll.cpp
格式:http://地址/%count%/%Project%/raw/%commitID%/%Path%/%File%
注意,使用curl直接下载可能不会成功,需要在gitlab中设置“access tokens”,在curl加上header选项
curl.exe --header "PRIVATE-TOKEN: 你的token" 你的url -O
拉取命令:curl 地址 -O [文件名]
如果使用cmd可以不添加文件名,使用Powershell必须添加文件名。
错误之处,多多指正!
[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。
最后于 2020-10-28 14:45
被comor编辑
,原因: 格式修改