Exploiting-The-DRAM-Rowhammer-Bug-To-Gain-Kernel-Privileges.pdf阅读整理

它是什么

重复行激活可导致相邻的行位翻转

翻转导致可能的权限位变化

2003 paper: “Using Memory Errors to Attack a Virtual Machine”

  • by Sudhakar Govindavajhala, Andrew Appel
  • Escape from Java VM

完全随机的 vs 可控和可重复的

  • 触发方式相近
  • 但可重复的能提供更多控制力

2014 paper: “Flipping Bits in Memory Without Accessing Them: An Experimental Study of DRAM Disturbance Errors”

  • 在一些桌面电脑测试,但它们有ECC – 能强力减轻这种bug

DRAM badness by year graph

如何触发/触发方法

1
2
3
4
5
6
7
code1a:
mov (X), %eax // Read from address X
mov (Y), %ebx // Read from address Y
clflush (X) // Flush cache for address X
clflush (Y) // Flush cache for address Y
// mfence // In CMU paper, but not actually needed
jmp code1a

必要条件1: 绕过cache 直接访问 → x86 CLFLUSH 指令

  • 它是非特权指令
  • 无法禁用它(不像RDTSC)

必要条件2: 找到坏行

  • 有一些的DRAM的坏行比其它的DRAM多
  • 申请大块内存,尝试很多地址

DRAM 被分成了 banks → 每一个有它当前的行
必要条件3: 选中>=2个地址

  • 映射同一个bank的不同行
  • 行的地址冲突对(CMU 论文用的: Y = X + 8MB)
  • 需要能用物理地址
  • Memtest: 在管理权限下运行 完全在硬件上的
  • On Linux: 可以使用 /proc/$PID/pagemap
Row # Bank 0 Bank 1 Bank 2 Bank 7
0 0 0x2000 0x4000 0xe000
1 0x10000 0x12000 0x14000 0x1e000
128… 0x800000 0x802000 0x804000 0x80e000

如果是随机地址

  • 那么有8 banks → 1/8 机会导致行冲突

根据上面得出的精炼结论是: 尝试的地址数量 >2 addresses, 比如 4 或 8 个

  • 一次测试更多的行
  • 增加行冲突的机会
  • 硬件通常有多个访问队列

Double-sided row hammering

  • 激活这两个邻国的一行,不仅仅是少了一个数据
  • 现有的论文还没探索

探索出DRAM 地址的映射机制

  • 通过位翻转观察
  • 通过时间
    选择地址
  • 使用物理地址 – 禁用 /proc/PID/pagemap
  • 大页(2MB) – 不被禁用
  • 其它连续的物理块

查询DRAM 的SPD 数据 sudo decode-dimms

以上理论的结果: rowhammer-test

  • 在用户态运行 申请1GB 等待位翻转
  • 风险:可能破坏其它进程或者内核 在试验中 它也的确发生了

它在2014年还测了更多的机器

根据以上得出的精炼结论是:

  • 难度:易 找到冲突地址对 ( 通过运行一定时间 , 找到坏行更快) 也就是知道映射关系
  • 难度:易 在128ms(2倍行刷新时间)内 真实的产生这个bug ( 通过最大化行刷新时间间隔中的行激活 通过最大化造成坏行的机会(比如上面的一次多行))
  • 难度:较难 能利用(2-sided) ( 需要更多的物理地址知识)

如何利用/可利用性

系统一直依赖内存

两个利用的地方

本地(NaCl)的Chrome 沙箱

  • 位翻转会被判为安全代码
  • 可以让chrome读代码来发现位翻转

Linux 内核权限提升

  • 在页表入口(PTE)翻转
  • 获得页表读写权

密集的数据结构

本地客户端介绍(NaCl)

  • 运行C/C++源码的沙箱
  • Chrome 的一部分
  • 类似Asm.js, 但是代码生成器是不可信的
  • 安全子集的x86——软件故障隔离(x86安全检测,但它允许CLFLUSH指令)
  • 两个变体: PNaCl(on open web. Runs pexe (LLVM bitcode): compiled to nexe by in-browser translator. No CLFLUSH?),NNaCl(in Chrome Web Store. Could use CLFLUSH.)
  • 作者用的是NaCl :-)

利用 NaCl

安全命令序列:

1
2
3
4
andl $~31, %eax // Truncate address to 32 bits
// and mask to be 32-byte-aligned.
addq %r15, %rax // Add %r15, the sandbox base address.
jmp *%rax // Indirect jump.

NaCl 沙箱模型:

  • 防止跳到x86指令中间(意思是比如一条指令是 01 02 03 那么禁止跳到 02 开始的位置)
  • 直接跳转目标只能用32位 对齐地址

位翻转导致部安全的方式

  • 可能导致允许跳转到非32位对齐的地址
  • 制作很多这个序列的备份 – 动态创代码(找寻位翻转 – 代码可读性)
  • 利用改变寄存器号(13%的位翻转可利用,测试驱动开发)

NaCl 沙箱地址空间(1GB~4GB)

读写执性 大小
stack (initial thread) read+write
available for mmap() anything but exec
nexe rwdata segment read+write variable size
nexe rodata segment read variable size
dynamic code area read+exec ~256MB
nexe code segment read+exec variable size
NaCl syscall trampolines read+exec 64k
zero page no access 64k

隐藏不安全代码的方法 in NaCl

  • 已存在利用”跳到代码中间”的技术Existing technique for exploiting non-bundle-aligned jump:

20ea0: 48 b8 0f 05 eb 0c f4 f4 f4 f4

movabs $0xf4f4f4f40ceb050f, %rax

隐藏以后:
20ea2: 0f 05 syscall

20ea4: eb 0c jmp … // Jump to next hidden instr

20ea6: f4 hlt // Padding

NaCl 减轻rowhammer的方法

  • 不允许 CLFLUSH
  • 也许对Hide code并没办法

利用 Kernel

x86页表条目(PTE)是密集的可信的

  • 他们控制物理内存访问权限,位翻转可以导致一个进程有权限访问另一个物理地址
  • 利用的目标: 得到页表访问权->得到所有物理地址的访问权
  • 尽量增大位翻转的有用性(用页表spray物理地址,先检测有用和可重复的位)

x86-64 Page Table Entries (PTEs)

Page table is a 4k page containing array of 512 PTEs

  • Each PTE is 64 bits, containing: graph

可以翻转 :

  • 2% 的机会 可写位1bit
  • 31% 的机会 物理地址号: 20位/4GB 系统

What happens when we repeatedly map a file with read-write permissions?

  1. PTEs in physical memory help resolve virtual addresses to physical pages.
  2. We can fill physical memory with PTEs. graphs
  3. Each of them points to pages in the same physical file mapping.
  4. If a bit in the right place in the PTE flips
  5. the corresponding virtual address now points to a wrong physical page - with RW access.
  6. Chances are this wrong page contains a page table itself.
  7. An attacker that can read / write page tables can use that to map any memory read-write.

利用策略 (特权提升 7 个简单的步骤)

  1. Allocate a large chunk of memory
  2. Search for locations prone to flipping
  3. Check if they fall into the “right spot” in a PTE for allowing the exploit
  4. Return that particular area of memory to the operating system
  5. 通过申请大量的地址空间 强迫系统为PTEs重用内存
  6. 引起位翻转 即改变PTE的指向
  7. Abuse R/W access to all of physical memory In practice, there are many complications.

可能出现的问题

  1. 第6步 如果文件在内存中是连续的一块,有可能我们改变了PTE的指向 但是它任然指向的是文件内部 而非页表的部分 (解决方案:尽力分化文件在内存中所占的位置为分散的)
  2. 第5步 很难让系统有规律的为PTE重用内存(作者说:我花了几个下午以某种方式探索Linux物理页分配器。不是很有趣的代码,结论Mark很聪明 他把系统内存压力逼到某个角落 系统表现得很好)

减轻rowhammer

  • CMU paper: “The industry has been aware of this problem since at least 2012”
  • 行业打算去减轻,但没有安全通告
  • ECC(错误纠正机制 一位错纠正 两位错检测 3位以上没有但可能性很小) 但前提是运行的机器使用了ECC 评价:该减轻方案不理想 昂贵 不能保证工作
  • TRR(目标行刷新) “理想”的方案 统计被激活行的次数 当达到阈值时刷新邻行(LPDDR4在使用,内存控制器pTRR,Intel也说Ivy桥用pTRR 虽然并没找到证据?)
  • 更高的DRAM刷新率,2x刷新率 当前CPU支持 很多厂商BIOS里可以设置这个参数tREFI(怎么验证刷新率?2x就够了么?)

我们能利用javascript 搞事情吗(产生rowhammer)

通过正常缓存地址的访问在不适用CLFLUSH的情况下

通过生成大量的cache misses

JS的引擎速度不是问题 接近原生的访问数组 比如Asm.js

cache missed 是缓慢的

lavados正在搞这个

引发cache misses

需要在所有cache层 都miss (L1, L2, L3)

Row hammering by accident in benchmarks (see paper)

Not with an inclusive cache

  • 被驱逐的cache line 从 L1 L2 L3 都被驱逐
  • 用的是Intel 的CPUs

获取cache配置算法/找到L3 cache相同的映射关系

比如 12路的 L3 cache 找13个地址 依次访问一定会造成一次miss 见paper: The Spy in the Sandbox – Practical Cache Attacks in Javascript

  • 通过一定时间的内存访问
  • 原始动机:L3 cache side channel 攻击

Cache 剔除方案

  • LRU 对于 12路cache 每次循环会发生13次misses
  • 减少6.5倍行激活。不理想
  • 理想的是每个迭代2个cache misses

真实CPU

  • Sandy Bridge: bit 伪 LRU 1bit/1cache line
  • Ivy Bridge : Quad Age LRU 2bit/cache line
  • 增加适应性: “设置决斗(set duelling)”

通过 Cache side channel 减弱rowhammer

  • 减少时间精度(performance.now()) Changes in Firefox, Chrome, Safari/WebKit

也许没用

  • 用更长的时间还是可以获知cache配置算法
  • 多线程: 建立自己的时钟 ( PNaCl, SharedArrayBuffers in Javascript WebAssembly )
  • CPU 性能计数器

未知:

  • ARM 和 移动设备 (cache 组织? CPU性能 和 内存控制器)
  • 损坏 Anecdotal observations

总结

作为软件层面沙箱越来越吊,攻击者将去玩更深奥的缺陷,如硬件错误

Rowhammer: 不只是可靠性的问题

难判定硬件达到了标准

Mailing list

总结

利用clflUSH可以触发rowhammer,并找出提高触发率的一些访问方式(一轮多组 找冲突对)

通过作者提供的方案步骤可以利用rowhammer

有ECC TRR 提高刷新频率等应对/解决/减弱的方案

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
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
<!DOCTYPE HTML>
<htmllang="en-US">
<head>
<meta charset="UTF-8">
<title>CSS3 Full Background Slider </title>
<style type="text/css">
@importurl("http://www.w3cplus.com/demo/css3/base.css");
@importurl("http://fonts.googleapis.com/css?family=Yesteryear");
html,body {
height: 100%;
margin:0px;
}
/*设置背景图片全屏显示,并且居中*/
img.bg {
min-height: 100%;
min-width: 1024px;
width: 100%;
height: auto !important;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index:1;
}
/*设置背景图片从左向右移入显示的动画效果*/
/* Slide Left */

@-webkit-keyframes 'slideLeft' {
0% { left: -100%; }
100% { left: 0; }
}
@-moz-keyframes 'slideLeft' {
0% { left: -100%; }
100% { left: 0; }
}
@-o-keyframes 'slideLeft' {
0% { left: -100%; }
100% { left: 0; }
}
@-ms-keyframes 'slideLeft' {
0% { left: -100%; }
100% { left: 0; }
}
@keyframes 'slideLeft' {
0% { left: -100%; }
100% { left: 0; }
}
/*设置背景图像从底部向顶部移入的动画效果*/
/* Slide Bottom */

@-webkit-keyframes 'slideBottom' {
0% { top: 350px; }
100% { top: 0; }
}
@-moz-keyframes 'slideBottom' {
0% { top: 350px; }
100% { top: 0; }
}
@-ms-keyframes 'slideBottom' {
0% { top: 350px; }
100% { top: 0; }
}
@-o-keyframes 'slideBottom' {
0% { top: 350px; }
100% { top: 0; }
}
@keyframes 'slideBottom' {
0% { top: 350px; }
100% { top: 0; }
}
/*设置背景图片由小到大放大动画效果*/
/* Zoom In */

@-webkit-keyframes 'zoomIn' {
0% { -webkit-transform: scale(0.1); }
100% { -webkit-transform: none; }
}
@-moz-keyframes 'zoomIn' {
0% { -moz-transform: scale(0.1); }
100% { -moz-transform: none; }
}
@-ms-keyframes 'zoomIn' {
0% { -ms-transform: scale(0.1); }
100% { -ms-transform: none; }
}
@-o-keyframes 'zoomIn' {
0% { -o-transform: scale(0.1); }
100% { -o-transform: none; }
}
@keyframes 'zoomIn' {
0% { transform: scale(0.1); }
100% { transform: none; }
}
/*设置背景图像由大到小缩小动画效果*/
/* Zoom Out */

@-webkit-keyframes 'zoomOut' {
0% { -webkit-transform: scale(2); }
100% { -webkit-transform: none; }
}
@-moz-keyframes 'zoomOut' {
0% { -moz-transform: scale(2); }
100% { -moz-transform: none; }
}
@-ms-keyframes 'zoomOut' {
0% { -ms-transform: scale(2); }
100% { -ms-transform: none; }
}
@-o-keyframes 'zoomOut' {
0% { -o-transform: scale(2); }
100% { -o-transform: none; }
}
@keyframes 'zoomOut' {
0% { transform: scale(2); }
100% { transform: none; }
}
/*背景图像旋转出现动画效果*/
/* Rotate */

@-webkit-keyframes 'rotate' {
0% { -webkit-transform: rotate(-360deg) scale(0.1); }
100% { -webkit-transform: none; }
}
@-moz-keyframes 'rotate' {
0% { -moz-transform: rotate(-360deg) scale(0.1); }
100% { -moz-transform: none; }
}
@-ms-keyframes 'rotate' {
0% { -ms-transform: rotate(-360deg) scale(0.1); }
100% { -ms-transform: none; }
}
@-o-keyframes 'rotate' {
0% { -o-transform: rotate(-360deg) scale(0.1); }
100% { -o-transform: none; }
}
@keyframes 'rotate' {
0% { transform: rotate(-360deg) scale(0.1); }
100% { transform: none; }
}
/*设置背景图像不显示动画效果*/
@-webkit-keyframes 'notTarget' {
0% { z-index: 75; }
100% { z-index: 75; }
}
@-moz-keyframes 'notTarget' {
0% { z-index: 75; }
100% { z-index: 75; }
}
@-ms-keyframes 'notTarget' {
0% { z-index: 75; }
100% { z-index: 75; }
}
@-o-keyframes 'notTarget' {
0% { z-index: 75; }
100% { z-index: 75; }
}
@keyframes 'notTarget' {
0% { z-index: 75; }
100% { z-index: 75; }
}



.slider {
position: absolute;
width: 100%;
text-align: center;
z-index: 9999;
bottom: 100px;
}
.slider li {
display: inline-block;
width: 170px;
height: 130px;
margin-right: 15px;
}
.slider a {
display: inline-block;
width: 170px;
padding-top: 70px;
padding-bottom: 20px;
position: relative;
cursor: pointer;
border: 2px solid #fff;
border-radius: 5px;
vertical-align: top;
color: #fff;
text-decoration: none;
font-size: 22px;
font-family: 'Yesteryear', cursive;
text-shadow: -1px -1px 1px rgba(0, 0, 0, 0.8),-2px -2px 1px rgba(0, 0, 0, 0.3),-3px -3px 1px rgba(0, 0, 0, 0.3);
}
/*任务一、设置不同列表的背景色*/

.slider ul li:nth-of-type(1) a{
background-color: #02646e;
}
.slider ul li:nth-of-type(2) a{
background-color: #eb0837;
}
.slider ul li:nth-of-type(3) a{
background-color: #67b374;
}
.slider ul li:nth-of-type(4) a{
background-color: #e6674a;
}
.slider ul li:nth-of-type(5) a{
background-color: #e61061;
}
/*任务二、设置缩略图形状*/
.slider li a::after{
content:"";
display: block;
height: 120px;
width: 120px;
border: 5px solid #fff;
border-radius: 50%;
position: absolute;
left: 50%;
margin-left: -60px;
z-index: 9999;
top: -80px;
}
/*任务三、设置缩略图背景图像*/
.slider li:nth-of-type(1) a::after{
background: url(http://p4.gexing.com/G1/M00/FB/8B/rBACFFI7u2uAcq4hAAEv1xanw5U252_200x200_3.png) no-repeat center;
}
.slider li:nth-of-type(2) a::after{
background: url(http://p3.gexing.com/G1/M00/69/21/rBACE1IHPUqBNBNYAAAU5l5wy0A616_200x200_3.jpg) no-repeat center;
}
.slider li:nth-of-type(3) a::after{
background: url(http://p2.gexing.com/G1/M00/67/3B/rBACFFIHj6fDFir7AAAhiX6dWfU282_200x200_3.jpg) no-repeat center;
}
.slider li:nth-of-type(4) a::after{
background: url(http://p3.gexing.com/G1/M00/34/D7/rBACE1H571HghyoyAAAVy0AOsB4191_200x200_3.jpg) no-repeat center;
}
.slider li:nth-of-type(5) a::after{
background: url(http://p3.gexing.com/G1/M00/A2/33/rBACFFIXQTazRAqrAAAWv2gMpjs851_200x200_3.jpg) no-repeat center;
}
/*任务四、给缩略图添加蒙板效果*/
.slider li a::before{
content:"";
display: block;
height: 120px;
width: 120px;
border: 5px solid #fff;
border-radius: 50%;
position: absolute;
left: 50%;
margin-left: -60px;
z-index: 99999;
top: -80px;
background: rgba(0,0,0,0.3);
}
/*任务五、鼠标悬浮时,修改缩略图蒙板透明度*/
.slider li:hover a::before{
opacity:0;
}
/*任务六、点击综略图,切换背景图*/
/*背景图从左向右出现*/
:target[class*=slideLeft]{
z-index: 100;
-webkit-animation-name: slideLeft;
-webkit-animation-duration: 1s;
-webkit-animation-iteration-count: 1;
-moz-animation-name: slideLeft;
-moz-animation-duration: 1s;
-moz-animation-iteration-count: 1;
-ms-animation-name: slideLeft;
-ms-animation-duration: 1s;
-ms-animation-iteration-count: 1;
-o-animation-name: slideLeft;
-o-animation-duration: 1s;
-o-animation-iteration-count: 1;
animation-name: slideLeft;
animation-duration: 1s;
animation-iteration-count: 1;
}
/*背景图从下向上出现*/
:target[class*=slideBottom]{
z-index: 100;

-webkit-animation-name: slideBottom;
-webkit-animation-duration: 1s;
-webkit-animation-iteration-count: 1;
-moz-animation-name: slideBottom;
-moz-animation-duration: 1s;
-moz-animation-iteration-count: 1;
-ms-animation-name: slideBottom;
-ms-animation-duration: 1s;
-ms-animation-iteration-count: 1;
-o-animation-name: slideBottom;
-o-animation-duration: 1s;
-o-animation-iteration-count: 1;
animation-name: slideBottom;
animation-duration: 1s;
animation-iteration-count: 1;
}
/*背景图由小到大出现*/
:target[class*=zoomIn]{
z-index: 100;
-webkit-animation-name: zoomIn;
-webkit-animation-duration: 1s;
-webkit-animation-iteration-count: 1;
-moz-animation-name: zoomIn;
-moz-animation-duration: 1s;
-moz-animation-iteration-count: 1;
-ms-animation-name: zoomIn;
-ms-animation-duration: 1s;
-ms-animation-iteration-count: 1;
-o-animation-name: zoomIn;
-o-animation-duration: 1s;
-o-animation-iteration-count: 1;
animation-name: zoomIn;
animation-duration: 1s;
animation-iteration-count: 1;
}

/*背景图由大到小出现*/
:target[class*=zoomOut]{
z-index: 100;
-webkit-animation-name: zoomOut;
-webkit-animation-duration: 1s;
-webkit-animation-iteration-count: 1;
-moz-animation-name: zoomOut;
-moz-animation-duration: 1s;
-moz-animation-iteration-count: 1;
-ms-animation-name: zoomOut;
-ms-animation-duration: 1s;
-ms-animation-iteration-count: 1;
-o-animation-name: zoomOut;
-o-animation-duration: 1s;
-o-animation-iteration-count: 1;
animation-name: zoomOut;
animation-duration: 1s;
animation-iteration-count: 1;
}

/*背景图旋转出现*/
:target[class*=rotate]{
z-index: 100;
-webkit-animation-name: rotate;
-webkit-animation-duration: 1s;
-webkit-animation-iteration-count: 1;
-moz-animation-name: rotate;
-moz-animation-duration: 1s;
-moz-animation-iteration-count: 1;
-ms-animation-name: rotate;
-ms-animation-duration: 1s;
-ms-animation-iteration-count: 1;
-o-animation-name: rotate;
-o-animation-duration: 1s;
-o-animation-iteration-count: 1;
animation-name: rotate;
animation-duration: 1s;
animation-iteration-count: 1;
}
/*任务七、设置不显示的背景图层级*/
/* Not Target */

img:not(:target){
-webkit-animation-name: notTarget;
-webkit-animation-duration: 1s;
-webkit-animation-iteration-count: 1;
-moz-animation-name: notTarget;
-moz-animation-duration: 1s;
-moz-animation-iteration-count: 1;
-ms-animation-name: notTarget;
-ms-animation-duration: 1s;
-ms-animation-iteration-count: 1;
-o-animation-name: notTarget;
-o-animation-duration: 1s;
-o-animation-iteration-count: 1;
animation-name: notTarget;
animation-duration: 1s;
animation-iteration-count: 1;
}
</style>
</head>
<body>
<div class="slider">
<ul class="clearfix">
<li><a href="#bg1">_(:з」∠)_</a></li>
<li><a href="#bg2">(●´∀‘●)</a></li>
<li><a href="#bg3">(。・`ω´・)</a></li>
<li><a href="#bg4">(〃∇〃)</a></li>
<li><a href="#bg5">(╯' - ')╯︵ ┻━┻</a></li>
</ul>
</div>
<img src="http://img4.duitang.com/uploads/item/201404/10/20140410201316_4shKU.jpeg" alt="" class="bg slideLeft" id="bg1" />
<img src="http://img5q.duitang.com/uploads/item/201406/01/20140601100050_afKZt.jpeg" alt="" class="bg slideBottom" id="bg2" />
<img src="http://cdn.duitang.com/uploads/item/201404/10/20140410101759_8Wd4T.jpeg" alt="" class="bg zoomIn" id="bg3" />
<img src="http://img5.duitang.com/uploads/item/201404/10/20140410095203_Ey8z3.jpeg" alt="" class="bg zoomOut" id="bg4" />
<img src="http://cdn.duitang.com/uploads/item/201404/10/20140410102139_ZQdPU.jpeg" alt="" class="bg rotate" id="bg5" />
</body>
</html>

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
<!DOCTYPE html>
<html>
<head>
<title>CSS3 ao you logo</title>
<style type="text/css">
* {margin:0; padding:0}
.main {width:240px;margin: 0px auto;}
.main_wrapper {width:240px; height:240px; border-radius:120px; background:#B1E4FF; border:2px solid #789CB6; box-shadow:5px 5px 7px #999}
.main_wrap {width:230px; height:230px; border-radius:115px; position:relative; top:5px; left:5px; background:#3B99E3}
.white_1 {width:150px; height:100px; background:#FFF; position:relative; left:42px; top:70px; border-radius:3px 20px 3px 3px}
.white_2 {width:35px; height:45px; background:#FFF; position:relative; left:33px; top:30px; border:25px solid #3B99E3}
</style>
</head>
<body>
<div class="main">
<div class="main_wrapper">
<div class="main_wrap">
<div class="white_1">
<div class="white_2"></div>
</div>
</div>
</div>
</div>
</body>
</html>

String:
String.format
str.trim();// 返回 去前导 尾部空格 的字符串
import java.util.StringTokenizer;//P113
StringTokenizer(String str,String delim);//str 要去除空格的字符串 delim要去除的字符 返回去除后结果
StringBuffer
str.replaceAll(String regex,String replacement);//正则表达式
str.replace(String regex,String replacement);//字符(串)的替换
str.replaceFirst(regex,replacement);
str.split(delim);//会分出 无长字符
str.matches(String regex);//判断是否正则表达式
汉子匹配P133

StringBuilder:
.append(String str);
.append(StringBuffer str);
.insert(int offset,String str);

时间:
System.currentTimeMillis();//系统时间
Date date = new Date(); // 创建Date对象date

多个类文件前面要加package com.lzw;

import java.text.DecimalFormat;
DecimalFormat myFormat = new DecimalFormat(pattern);// 实例化DecimalFormat对象
String output = myFormat.format(value);
System.out.println(Object X)->调用String.valueof(X)->X.toString();//
自定义Class 调用Object默认的equals
getClass().getName();

不定长
public static int add(int… a) { // 定义不定长参数方法
int s = 0;
for (int i = 0; i < a.length; i++)
// 根据参数个数做循环操作
s += a[i]; // 将每个参数累加
return s; // 将计算结果返回
}
add(1,2, 3,4, 5,6, 7, 8, 9);

10.10 接口 向上转型

A instanceof B;A和B的关系要是 A extends B or B extends A//返回A是否为B的子类
抽象类不能实例化

new innerClass 11.07;
接口向上转型 直接调用内部类 11.08
e.printStackTrace;//catch (MyException e)

WindowConstants.DISPOSE_ON_CLOSE
||
JFrame.DISPOSE_ON_CLOSE

数据库:
加入数据
String sql= insert into tb_users (username,password,sex,age) values(‘adf’,’111’,’nan’,’22’)
Statement stmt = conn.createStatement();
stmt.executeUpdate(sql);

String Sql =insert into tb_users (username,password,sex,age)value(?,?,?,?);
PreparedStatement ps =conn.prepareStatement(sql);
ps.setString(1,””);
ps.setString(2,””);
ps.setString(3,””);
ps.executeUpdate();
获得数据
String sql=select * from tb_users;
Statement stmt = conn.createStatement();
ResultSet rs =stmt.executeQuery(sql);
while(rs.next()){
=rs.getInt(“id”);
=rs.getStringInt(2);
=rs.getString(“password”);
=rs.getInt(4);
}

更改数据
String sql=”update tb_users set age=20 where id=1”
Statement stmt = conn.createStatement();
stmt.executeUpdate(sql);

String sql=”update tb_users set password=? where sex=?”
PreparedStatement ps=conn.prepareStatement(sql);
ps.setString(1,”admin”);
ps.setString(2,”nan”);
int count=ps.executeUpdate();
删除数据
String sql=”delete from tb_users where id=1”
Statement stmt=conn.createStatement();
stmt.executeUpdate;
模糊查询
Statement stmt=conn.createStatement();
String sql=”select * from tb_users where username like ‘%李%’”;//通配符%=0个或多个字符 下划线_=一个字符
ResultSet rs =stmt.executeQuery(sql);
while(rs.next()){
=rs.getInt(“id”);
=rs.getStringInt(2);
=rs.getString(“password”);
=rs.getInt(4);
}

0%