webkit调试方法记录

调试crash的准备工作

下载 Webkit 源代码并编译:

1
2
3
4
5
-> git clone git://git.webkit.org/WebKit.git WebKit

for macOS:
-> Tools/Scripts/set-webkit-configuration --asan --debug
-> Tools/Scripts/build-webkit

切换到漏洞影响的分支

1
git checkout -b localname commithash

调试
使用的调试器是 lldb. 通过以下命令运行 Safari:

1
-> Tools/Scripts/run-safari

或者获取源码后直接在xcode里打开webkit,


测试

测试,找一个poc运行,可以看到asna打印uaf。

run-jsc

通过run-jsc这个script我们能打印出JIT的log

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
35
36
37
38
39
40
41
sakura@sakuradeMBP:~/WebKit/Tools/Scripts$ pwd
/Users/sakura/WebKit/Tools/Scripts
sakura@sakuradeMBP:~/WebKit/Tools/Scripts$ ls | grep run-js
run-jsc
sakura@sakuradeMBP:~/WebKit/Tools/Scripts$ ./run-jsc --help
Running 1 time(s): DYLD_FRAMEWORK_PATH=/Users/sakura/WebKit/WebKitBuild/Debug /Users/sakura/WebKit/WebKitBuild/Debug/jsc --help
Usage: jsc [options] [files] [-- arguments]
-d Dumps bytecode (debug builds only)
-e Evaluate argument as script code
-f Specifies a source file (deprecated)
-h|--help Prints this help message
-i Enables interactive mode (default if no files are specified)
-m Execute as a module
-s Installs signal handlers that exit on a crash (Unix platforms only)
-p <file> Outputs profiling data to a file
-x Output exit code before terminating

--sample Collects and outputs sampling profiler data
--test262-async Check that some script calls the print function with the string 'Test262:AsyncTestComplete'
--strict-file=<file> Parse the given file as if it were in strict mode (this option may be passed more than once)
--module-file=<file> Parse and evaluate the given file as module (this option may be passed more than once)
--exception=<name> Check the last script exits with an uncaught exception with the specified name
--watchdog-exception-ok Uncaught watchdog exceptions exit with success
--dumpException Dump uncaught exception text
--options Dumps all JSC VM options and exits
--dumpOptions Dumps all non-default JSC VM options before continuing
--<jsc VM option>=<value> Sets the specified JSC VM option

选项 描述
JSC_dumpDisassembly = true 转储所有JIT编译函数的反汇编。
JSC_dumpDFGDisassembly = true 转储DFG和FTL编译函数的反汇编。
JSC_dumpFTLDisassembly = true 转储FTL编译函数的反汇编。
JSC_dumpSourceAtDFGTime = true 转储DFG/FTL编译函数的来源。
JSC_dumpBytecodeAtDFGTime = true 转储DFG/FTL编译函数的字节码。
JSC_dumpGraphAfterParsing = true 在DFG/FTL编译时解析函数字节码后转储DFG图。
JSC_dumpGraphAtEachPhase = true 在DFG/FTL编译的每个阶段之后转储DFG图。

例如
./run-jsc --dumpGraphAtEachPhase=true /Users/sakura/Desktop/for-in-side-effects.js &> ~/log.txt

./run-jsc --dumpDisassembly=true /Users/sakura/Desktop/for-in-side-effects.js &> ~/log.txt

for-in-side-effects.js

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// Regression test for bug 179212

var p = { "a": {} };

var flag = 0;
var data = [];
var copy = [];

var z = new Proxy({}, {
getPrototypeOf: function() {
if (flag == 2) {
data[0] = { "x": "I changed" };
}

if (flag == 1) {
flag = 2;
}

return {"a": 1, "b": 2}
}
});

p.__proto__ = z;

function reset()
{
flag = 0;
data = [1.1, 2.2, 3.3];
copy = [];
}

function runTest(func)
{
reset();

for (var i = 0; i < 0x10000; i++)
func();

flag = 1;
func();

if (copy[0].x != "I changed")
throw "Expected updated value for copy[0]";
}


function testWithFTL()
{
function f()
{
data[0] = 2.2;
for(var d in p) {
copy[0] = data[0];
copy[1] = data[1];
copy[2] = data[2];
}
}

runTest(f);
}

testWithFTL();

jsc运行报错

1
2
3
sakura@sakuradeMBP:~/WebKit/WebKitBuild/Debug$ export DYLD_FRAMEWORK_PATH=~/WebKit/WebKitBuild/Debug
sakura@sakuradeMBP:~/WebKit/WebKitBuild/Debug$ ./jsc
>>> quit()

其他

https://webkit.org/blog/6411/javascriptcore-csi-a-crash-site-investigation-story/