-
Notifications
You must be signed in to change notification settings - Fork 0
/
ptrace函数.html
803 lines (475 loc) · 78.9 KB
/
ptrace函数.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
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
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
<!DOCTYPE html>
<html class="theme-next pisces" lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="generator" content="Hexo 3.9.0">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="google-site-verification" content="5kQ1pLcJBOrSXQ4-tRz_R_V6TfGCs1Jls9WuWt6-l6w">
<meta name="sogou-site-verification" content="nOkR7Wa5yE">
<meta name="360-site-verification" content="998ba408010b57a9856982d547a1cf5c">
<meta name="baidu-site-verification" content="pO45hC5Gb2">
<link rel="apple-touch-icon" sizes="180x180" href="/images/headicon.png?v=7.2.0">
<link rel="icon" type="image/png" sizes="32x32" href="/images/headicon.png?v=7.2.0">
<link rel="icon" type="image/png" sizes="16x16" href="/images/headicon.png?v=7.2.0">
<link rel="mask-icon" href="/images/headicon.svg?v=7.2.0" color="#222">
<link rel="stylesheet" href="/css/main.css?v=7.2.0">
<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css?v=4.7.0">
<link rel="stylesheet" href="//cdn.jsdelivr.net/fancybox/2.1.5/jquery.fancybox.min.css">
<script id="hexo.configurations">
var NexT = window.NexT || {};
var CONFIG = {
root: '/',
scheme: 'Pisces',
version: '7.2.0',
sidebar: {"position":"left","display":"post","offset":12,"onmobile":false},
back2top: {"enable":true,"sidebar":true,"scrollpercent":true},
copycode: {"enable":true,"show_result":true,"style":"mac"},
fancybox: true,
mediumzoom: false,
lazyload: false,
pangu: false,
algolia: {
applicationID: '',
apiKey: '',
indexName: '',
hits: {"per_page":10},
labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
},
localsearch: {"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},
search: {
root: '/',
path: ''
},
tabs: true,
motion: {"enable":false,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
translation: {
copy_button: '复制',
copy_success: '复制成功',
copy_failure: '复制失败'
}
};
</script>
<meta name="description" content="ptrace 函数简介函数原型123#include &lt;sys/ptrace.h&gt;long ptrace(enum _ptrace_request request,pid_t pid,void * addr ,void *data); 参数意义 request:请求ptrace执行的操作 pid:目标进程的ID addr:目标进程的地址 data:根据request的不同而变化">
<meta name="keywords" content="C,hook">
<meta property="og:type" content="article">
<meta property="og:title" content="ptrace函数">
<meta property="og:url" content="http://0xe4s0n.github.io/ptrace函数.html">
<meta property="og:site_name" content="0xE4s0n的博客">
<meta property="og:description" content="ptrace 函数简介函数原型123#include &lt;sys/ptrace.h&gt;long ptrace(enum _ptrace_request request,pid_t pid,void * addr ,void *data); 参数意义 request:请求ptrace执行的操作 pid:目标进程的ID addr:目标进程的地址 data:根据request的不同而变化">
<meta property="og:locale" content="zh-CN">
<meta property="og:image" content="https://i.loli.net/2019/08/14/KtmlU61q5J4OPz7.png">
<meta property="og:image" content="https://i.loli.net/2019/08/14/YQjikwv1FcmyVWH.png">
<meta property="og:image" content="https://i.loli.net/2019/08/14/4YGNst38d2kwX7M.png">
<meta property="og:image" content="https://i.loli.net/2019/08/14/jkwH3vUEAnsNbC2.png">
<meta property="og:image" content="https://i.loli.net/2019/08/14/Mfxh9bHiOA1znjQ.png">
<meta property="og:image" content="https://i.loli.net/2019/08/14/8zgKlcwUt1onEYJ.png">
<meta property="og:image" content="https://i.loli.net/2019/08/14/7du5aI6ZvnVOWDz.png">
<meta property="og:image" content="https://i.loli.net/2019/08/14/H5jefxws6g3h2io.png">
<meta property="og:image" content="https://i.loli.net/2019/08/14/aWvUMpZ8nfzT64s.png">
<meta property="og:image" content="https://i.loli.net/2019/08/14/xqY1XHKJTCQWuet.png">
<meta property="og:image" content="https://i.loli.net/2019/08/14/KyZ5oX2nIt9EVuG.png">
<meta property="og:image" content="https://i.loli.net/2019/08/14/ifrTU6M3X2gocPw.png">
<meta property="og:updated_time" content="2019-08-25T13:08:39.498Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="ptrace函数">
<meta name="twitter:description" content="ptrace 函数简介函数原型123#include &lt;sys/ptrace.h&gt;long ptrace(enum _ptrace_request request,pid_t pid,void * addr ,void *data); 参数意义 request:请求ptrace执行的操作 pid:目标进程的ID addr:目标进程的地址 data:根据request的不同而变化">
<meta name="twitter:image" content="https://i.loli.net/2019/08/14/KtmlU61q5J4OPz7.png">
<link rel="alternate" href="/atom.xml" title="0xE4s0n的博客" type="application/atom+xml">
<link rel="canonical" href="http://0xe4s0n.github.io/ptrace函数">
<script id="page.configurations">
CONFIG.page = {
sidebar: "",
};
</script>
<title>ptrace函数 | 0xE4s0n的博客</title>
<noscript>
<style>
.use-motion .motion-element,
.use-motion .brand,
.use-motion .menu-item,
.sidebar-inner,
.use-motion .post-block,
.use-motion .pagination,
.use-motion .comments,
.use-motion .post-header,
.use-motion .post-body,
.use-motion .collection-title { opacity: initial; }
.use-motion .logo,
.use-motion .site-title,
.use-motion .site-subtitle {
opacity: initial;
top: initial;
}
.use-motion .logo-line-before i { left: initial; }
.use-motion .logo-line-after i { right: initial; }
</style>
</noscript>
</head>
<body itemscope itemtype="http://schema.org/WebPage" lang="zh-CN">
<div class="container sidebar-position-left page-post-detail">
<div class="headband"></div>
<header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
<div class="header-inner"><div class="site-brand-wrapper">
<div class="site-meta">
<div class="custom-logo-site-title">
<a href="/" class="brand" rel="start">
<span class="logo-line-before"><i></i></span>
<span class="site-title">0xE4s0n的博客</span>
<span class="logo-line-after"><i></i></span>
</a>
</div>
</div>
<div class="site-nav-toggle">
<button aria-label="切换导航栏">
<span class="btn-bar"></span>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
</button>
</div>
</div>
<nav class="site-nav">
<ul id="menu" class="menu">
<li class="menu-item menu-item-home">
<a href="/" rel="section"><i class="menu-item-icon fa fa-fw fa-home"></i> <br/>首页</a>
</li>
<li class="menu-item menu-item-about">
<a href="/about/" rel="section"><i class="menu-item-icon fa fa-fw fa-user"></i> <br/>关于</a>
</li>
<li class="menu-item menu-item-tags">
<a href="/tags/" rel="section"><i class="menu-item-icon fa fa-fw fa-tags"></i> <br/>标签<span class="badge">4</span></a>
</li>
<li class="menu-item menu-item-categories">
<a href="/categories/" rel="section"><i class="menu-item-icon fa fa-fw fa-th"></i> <br/>分类<span class="badge">3</span></a>
</li>
<li class="menu-item menu-item-archives">
<a href="/archives/" rel="section"><i class="menu-item-icon fa fa-fw fa-archive"></i> <br/>归档<span class="badge">8</span></a>
</li>
</ul>
</nav>
</div>
</header>
<main id="main" class="main">
<div class="main-inner">
<div class="content-wrap">
<div id="content" class="content">
<div id="posts" class="posts-expand">
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="http://0xe4s0n.github.io/ptrace函数.html">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="0xE4s0n">
<meta itemprop="description" content="">
<meta itemprop="image" content="/images/headicon.png">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="0xE4s0n的博客">
</span>
<header class="post-header">
<h2 class="post-title" itemprop="name headline">ptrace函数
</h2>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2019-08-14 22:57:45" itemprop="dateCreated datePublished" datetime="2019-08-14T22:57:45+08:00">2019-08-14</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-check-o"></i>
</span>
<span class="post-meta-item-text">更新于</span>
<time title="修改时间:2019-08-25 21:08:39" itemprop="dateModified" datetime="2019-08-25T21:08:39+08:00">2019-08-25</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-folder-o"></i>
</span>
<span class="post-meta-item-text">分类于</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/linux/" itemprop="url" rel="index"><span itemprop="name">linux</span></a></span>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon"
>
<i class="fa fa-eye"></i>
阅读次数:
<span class="busuanzi-value" id="busuanzi_value_page_pv"></span>
</span>
</span>
<br/>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="ptrace-函数简介"><a href="#ptrace-函数简介" class="headerlink" title="ptrace 函数简介"></a>ptrace 函数简介</h1><h2 id="函数原型"><a href="#函数原型" class="headerlink" title="函数原型"></a>函数原型</h2><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/ptrace.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">long</span> ptrace(<span class="keyword">enum</span> _ptrace_request request,<span class="keyword">pid_t</span> pid,<span class="keyword">void</span> * addr ,<span class="keyword">void</span> *data);</span><br></pre></td></tr></table></figure>
<h2 id="参数意义"><a href="#参数意义" class="headerlink" title="参数意义"></a>参数意义</h2><ul>
<li><p><code>request</code>:请求ptrace执行的操作</p>
</li>
<li><p><code>pid</code>:目标进程的ID</p>
</li>
<li><p><code>addr</code>:目标进程的地址</p>
</li>
<li><p><code>data</code>:根据<code>request</code>的不同而变化,向目标进程写入数据时,<code>data</code>存放要写入的数据的地址;从目标进程中读数据时,<code>data</code>接收返回数据的地址<br><br><br> </p>
</li>
</ul>
<p><code>request</code>参数决定<code>ptrace</code>的行为以及后续的参数是如何被使用的,参数<code>request</code>的常用的值如下:<br><img src="https://i.loli.net/2019/08/14/KtmlU61q5J4OPz7.png" alt> </p>
<blockquote>
<p>更多参数请移步<a href="http://man7.org/linux/man-pages/man2/ptrace.2.html" target="_blank" rel="noopener">官方文档</a> 参数对应值参考<code>/usr/include/linux/ptrace.h</code><a href="https://0xe4s0n.github.io/download/De1ctf/ptrace.h">源码</a> </p>
</blockquote>
<h2 id="描述"><a href="#描述" class="headerlink" title="描述"></a>描述</h2><p>  <code>ptrace()</code>系统调用函数提供了一个进程(<code>the “tracer”</code><em>监视者</em>)监察和控制另一个进程(<code>the “tracee”</code><em>被监视者</em>)的方法。并且可以检查和改变<code>tracee</code>进程的内存和寄存器里的数据。它可以用来实现断点调试和系统调用跟踪。<br>  <code>tracee</code>首先需要被附着到<code>tracer</code>。在多线程进程中,每个线程都可以被附着到一个<code>tracer</code>。<code>ptrace</code>命令总是以<code>ptrace(PTARCE_foo,pid,..)</code>的形式发送到<code>tracee</code>进程。<code>pid</code>是<code>tracee</code>线程<code>ID</code>。<br>  一个进程可以通过调用<code>fork</code>函数创建子进程并让子进程执行<code>PTRACE_TRACEME</code>来初始化一个<code>ptrace</code>,然后通常子进程再调用<code>execve()</code>(如果当前进程被<code>ptrace</code>,<code>execve()</code>成功执行后 <code>SIGTRAP</code>信号量会被发送到当前进程)。一个进程也可以使用<code>PTRACE_ATTACH</code>或者<code>PTRACE_SEIZE</code>来跟踪另一个进程。<br>  当进程被跟踪后,每当信号量传给当前进程,甚至信号量被忽略时,<code>tracee</code>会暂停(<code>SIGKILL</code>除外)。<code>tracer</code>会在下次调用<code>waitpid</code>(或者其它<code>wait</code>系统调用)处被通知。该调用会返回一个包含<code>tracee</code>暂停原因信息的状态码。当<code>tracee</code>暂停后,<code>tracer</code>可以使用一系列<code>ptrace</code>请求来查看和修改<code>tracee</code>中的信息。<code>tracer</code>接着可以让<code>tracee</code>继续执行。<code>tracee</code>传递给<code>tracer</code>中的信号量通常被忽略(即使是一个不同的信号)。<br> 当<code>PTRACE_O_TRACEEXEC</code>项未起作用时,所有成功执行<code>execve()</code>的<code>tracee</code>进程会被发送一个 <code>SIGTRAP</code>信号量后暂停,在新程序执行之前,父进程将会取得该进程的控制权。<br> 当<code>tracer</code>结束跟踪后,可以通过调用<code>PTRACE_DETACH</code>让<code>tracee</code>在未被<code>trace</code>下继续执行。</p>
<p> 那么,<code>ptrace</code>会在什么时候出现呢?在执行系统调用之前,内核会先检查当前进程是否处于被“跟踪”(<code>traced</code>)的状态。如果是的话,内核暂停当前进程并将控制权交给跟踪进程,使跟踪进程得以察看或者修改被跟踪进程的寄存器。</p>
<h1 id="示例"><a href="#示例" class="headerlink" title="示例"></a>示例</h1><p>以下示例若无特殊说明均在该系统中测试</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Operating System: Ubuntu 19.04</span><br><span class="line">Kernel: Linux 5.0.0-19-generic</span><br><span class="line">Architecture: x86-64</span><br></pre></td></tr></table></figure>
<h2 id="追踪系统调用号"><a href="#追踪系统调用号" class="headerlink" title="追踪系统调用号"></a>追踪系统调用号</h2><h3 id="系统调用"><a href="#系统调用" class="headerlink" title="系统调用"></a>系统调用</h3><p>  操作系统提供了一种标准的服务来让程序员实现对底层硬件和服务的控制(比如文件系统),叫做系统调用(<code>system calls</code>)。当一个程序需要作系统调用的时候,它将相关参数放进系统调用相关的寄存器,然后以不同方式调用,就像一个让程序得以接触到内核模式的窗口,程序将参数和系统调用号交给内核,内核来完成系统调用的执行。 </p>
<blockquote>
<p>详见附录 <a href="#不同平台的系统调用方式">不同平台的系统调用方式</a> <a href="#不同平台使用的参数寄存器">不同平台使用的参数寄存器</a></p>
</blockquote>
<p>比如<code>Write(2, “Hello”, 5)</code>的<code>i386</code>汇编形式大概是这样的</p>
<figure class="highlight arm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">movl </span> <span class="number">$4</span>, %eax</span><br><span class="line"><span class="keyword">movl </span> <span class="number">$2</span>, %ebx</span><br><span class="line"><span class="keyword">movl </span> $hello, %ecx</span><br><span class="line"><span class="keyword">movl </span> <span class="number">$5</span>, %edx</span><br><span class="line"><span class="symbol">int</span> <span class="number">$0x80</span></span><br></pre></td></tr></table></figure>
<p>这里的<code>$hello</code>指向的是标准字符串<code>”Hello”</code>。</p>
<h3 id="开始追踪"><a href="#开始追踪" class="headerlink" title="开始追踪"></a>开始追踪</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><unistd.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/ptrace.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/types.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/wait.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/reg.h> /* For constants ORIG_RAX etc */</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">pid_t</span> child;</span><br><span class="line"> <span class="keyword">long</span> orig_rax;</span><br><span class="line"> child = fork();</span><br><span class="line"> <span class="keyword">if</span> (child == <span class="number">0</span>)</span><br><span class="line"> {</span><br><span class="line"> ptrace(PTRACE_TRACEME, <span class="number">0</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line"> execl(<span class="string">"/bin/ls"</span>, <span class="string">"ls"</span>, <span class="literal">NULL</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> wait(<span class="literal">NULL</span>);</span><br><span class="line"> orig_rax = ptrace(PTRACE_PEEKUSER, child, <span class="number">8</span> * ORIG_RAX, <span class="literal">NULL</span>);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"The child made a system call %ld\n"</span>, orig_rax);</span><br><span class="line"> ptrace(PTRACE_CONT, child, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>使用<code>gcc</code>编译该文件<code>gcc ptrace.c -o ptrace</code> 然后运行<br><img src="https://i.loli.net/2019/08/14/YQjikwv1FcmyVWH.png" alt><br><code>ptrcer</code>通过<code>PTRACE_PEEKUSER</code>访问<code>user</code>结构体读取<code>RAX</code>的值 第二个参数指定<code>RAX</code>在<code>user</code>中的偏移量。<br><img src="https://i.loli.net/2019/08/14/4YGNst38d2kwX7M.png" alt></p>
<blockquote>
<p>在<code>reg.h</code>中定义了各个变量在<code>user.h</code>中的偏移量,<br><code>/usr/include/x86_64-linux-gnu/reg.h</code><a href="https://0xe4s0n.github.io/download/De1ctf/reg.h">源码</a><br><code>/usr/include/x86_64-linux-gnu/user.h</code><a href="https://0xe4s0n.github.io/download/De1ctf/user.h">源码</a></p>
</blockquote>
<blockquote>
<p>59是<code>execve</code>的系统调用号,这是该程序调用的第一个系统调用。系统调用号的详细内容,<br>64位linux请察看 <a href="https://0xe4s0n.github.io/download/De1ctf/unistd_64.h">/usr/include/x86_64-linux-gnu/asm/unistd_64.h</a><br>32位linux请察看 <a href="https://0xe4s0n.github.io/download/De1ctf/unistd_32.h">/usr/include/i386-linux-gnu/asm/unistd_32.h</a></p>
</blockquote>
<p>  <code>execl()</code>函数对应的系统调用为<code>__NR_execve</code>,系统调用值为<code>59</code>。父进程通过调用<code>fork()</code>来创建子进程。在子进程中,先运行<code>patrce()</code>.请求参数设为<code>PTRACE_TRACE</code>,来告诉内核当前进程被父进程<code>trace</code>,每当有信号量传递到当前进程,该进程会暂停,提醒父进程在<code>wait()</code>调用处继续执行。然后再调用<code>execl()</code>。当<code>execl()</code>函数成功执行后,继续运行之前,<code>SIGTRAP</code>信号量会被发送到该进程,让子进程停止,这时父进程会在<code>wait</code>相关调用处被通知,获取子进程的控制权,可以查看子进程内存和寄存器相关信息。当检查完系统调用之后,调用ptrace并设置参数PTRACE_CONT让子进程继续进行。</p>
<h2 id="读取系统调用参数"><a href="#读取系统调用参数" class="headerlink" title="读取系统调用参数"></a>读取系统调用参数</h2><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ptrace(PTRACE_GETREGS, child, <span class="literal">NULL</span>, &regs);</span><br></pre></td></tr></table></figure>
<p><img src="https://i.loli.net/2019/08/14/jkwH3vUEAnsNbC2.png" alt></p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/ptrace.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/wait.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/reg.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/user.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/syscall.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><unistd.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">pid_t</span> child;</span><br><span class="line"> <span class="keyword">long</span> orig_rax;</span><br><span class="line"> <span class="keyword">int</span> status;</span><br><span class="line"> <span class="keyword">int</span> iscalling = <span class="number">0</span>;</span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">user_regs_struct</span> <span class="title">regs</span>;</span></span><br><span class="line"></span><br><span class="line"> child = fork();</span><br><span class="line"> <span class="keyword">if</span> (child == <span class="number">0</span>)</span><br><span class="line"> {</span><br><span class="line"> ptrace(PTRACE_TRACEME, <span class="number">0</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line"> execl(<span class="string">"/bin/ls"</span>, <span class="string">"ls"</span>, <span class="string">"-l"</span>, <span class="string">"-h"</span>, <span class="literal">NULL</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">while</span> (<span class="number">1</span>)</span><br><span class="line"> {</span><br><span class="line"> wait(&status);</span><br><span class="line"> <span class="keyword">if</span> (WIFEXITED(status))</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> orig_rax = ptrace(PTRACE_PEEKUSER, child, <span class="number">8</span> * ORIG_RAX, <span class="literal">NULL</span>);</span><br><span class="line"> <span class="keyword">if</span> (orig_rax == SYS_write)</span><br><span class="line"> {</span><br><span class="line"> ptrace(PTRACE_GETREGS, child, <span class="literal">NULL</span>, &regs);</span><br><span class="line"> <span class="keyword">if</span> (!iscalling)</span><br><span class="line"> {</span><br><span class="line"> iscalling = <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"SYS_write call with %lld, %lld, %lld\n"</span>, regs.rdi, regs.rsi, regs.rdx);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"SYS_write call return %lld\n"</span>, regs.rax);</span><br><span class="line"> iscalling = <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> ptrace(PTRACE_SYSCALL, child, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>结果<br><img src="https://i.loli.net/2019/08/14/Mfxh9bHiOA1znjQ.png" alt> </p>
<p>大部分的代码还是比较好懂,部分需要说明一下</p>
<p>对于<code>PTRACE_STSCALL</code>参数,该参数会像<code>PTRACE_CONT</code>一样使暂停的子进程继续执行,并在子进程下次进行系统调用前或系统调后,向子进程发送SINTRAP信号量,让子进程暂停。<br><img src="https://i.loli.net/2019/08/14/8zgKlcwUt1onEYJ.png" alt></p>
<p><code>WIFEXITED</code>函数(宏)函数用来检查子进程是暂停还准备退出。</p>
<p><code>SYS_write</code>被定义在<code>/usr/include/x86_64-linux-gnu/bits/syscall.h</code>里面<code># define SYS_write __NR_write</code>与<code>unistd.h</code>对应 <a href="https://0xe4s0n.github.io/download/De1ctf/syscall.h">源码</a></p>
<h2 id="修改子进程系统调用参数"><a href="#修改子进程系统调用参数" class="headerlink" title="修改子进程系统调用参数"></a>修改子进程系统调用参数</h2><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">val = ptrace(PTRACE_PEEKDATA,child,addr,<span class="literal">NULL</span>)</span><br><span class="line">val = ptrace(PTRACE_PEEKTEXT,child,addr,<span class="literal">NULL</span>)</span><br></pre></td></tr></table></figure>
<p><img src="https://i.loli.net/2019/08/14/7du5aI6ZvnVOWDz.png" alt></p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/ptrace.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/wait.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/reg.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/syscall.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/user.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><string.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><errno.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdlib.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><unistd.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> long_size sizeof(long)</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">reverse</span><span class="params">(<span class="keyword">char</span> *str)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">int</span> i, j;</span><br><span class="line"> <span class="keyword">char</span> temp;</span><br><span class="line"> <span class="keyword">for</span> (i = <span class="number">0</span>, j = <span class="built_in">strlen</span>(str) - <span class="number">2</span>; i <= j; ++i, --j)</span><br><span class="line"> {</span><br><span class="line"> temp = str[i];</span><br><span class="line"> str[i] = str[j];</span><br><span class="line"> str[j] = temp;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">getdata</span><span class="params">(<span class="keyword">pid_t</span> child, <span class="keyword">long</span> addr, <span class="keyword">char</span> *str, <span class="keyword">int</span> len)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">char</span> *laddr;</span><br><span class="line"> <span class="keyword">int</span> i, j;</span><br><span class="line"> <span class="keyword">union</span> u {</span><br><span class="line"> <span class="keyword">long</span> val;</span><br><span class="line"> <span class="keyword">char</span> chars[long_size];</span><br><span class="line"> } data;</span><br><span class="line"> i = <span class="number">0</span>;</span><br><span class="line"> j = len / long_size;</span><br><span class="line"> laddr = str;</span><br><span class="line"> <span class="keyword">while</span> (i < j)</span><br><span class="line"> {</span><br><span class="line"> data.val = ptrace(PTRACE_PEEKDATA, child, addr + i * long_size, <span class="literal">NULL</span>);</span><br><span class="line"> <span class="keyword">if</span> (data.val == <span class="number">-1</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (errno)</span><br><span class="line"> {</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"READ error: %s\n"</span>, strerror(errno));</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">memcpy</span>(laddr, data.chars, long_size);</span><br><span class="line"> ++i;</span><br><span class="line"> laddr += long_size;</span><br><span class="line"> };</span><br><span class="line"> j = len % long_size;</span><br><span class="line"> <span class="keyword">if</span> (j != <span class="number">0</span>)</span><br><span class="line"> {</span><br><span class="line"> data.val = ptrace(PTRACE_PEEKDATA, child, addr + i * long_size, <span class="literal">NULL</span>);</span><br><span class="line"> <span class="built_in">memcpy</span>(laddr, data.chars, j);</span><br><span class="line"> }</span><br><span class="line"> str[len] = <span class="string">'\0'</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">putdata</span><span class="params">(<span class="keyword">pid_t</span> child, <span class="keyword">long</span> addr, <span class="keyword">char</span> *str, <span class="keyword">int</span> len)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">char</span> *laddr;</span><br><span class="line"> <span class="keyword">int</span> i, j;</span><br><span class="line"> <span class="keyword">union</span> u {</span><br><span class="line"> <span class="keyword">long</span> val;</span><br><span class="line"> <span class="keyword">char</span> chars[long_size];</span><br><span class="line"> } data;</span><br><span class="line"> i = <span class="number">0</span>;</span><br><span class="line"> j = len / long_size;</span><br><span class="line"> laddr = str;</span><br><span class="line"> <span class="keyword">while</span> (i < j)</span><br><span class="line"> {</span><br><span class="line"> <span class="built_in">memcpy</span>(data.chars, laddr, long_size);</span><br><span class="line"> ptrace(PTRACE_POKEDATA, child, addr + i * long_size, data.val);</span><br><span class="line"> ++i;</span><br><span class="line"> laddr += long_size;</span><br><span class="line"> }</span><br><span class="line"> j = len % long_size;</span><br><span class="line"> <span class="keyword">if</span> (j != <span class="number">0</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="comment">//注意:由于写入时也是按字写入的,所以正确的做法是先将该字的高地址数据读出保存在data的高地址上 ,然后将该字再写入</span></span><br><span class="line"> <span class="built_in">memcpy</span>(data.chars, laddr, j);</span><br><span class="line"> ptrace(PTRACE_POKEDATA, child, addr + i * long_size, data.val);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">pid_t</span> child;</span><br><span class="line"> <span class="keyword">int</span> status;</span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">user_regs_struct</span> <span class="title">regs</span>;</span></span><br><span class="line"> child = fork();</span><br><span class="line"> <span class="keyword">if</span> (child == <span class="number">0</span>)</span><br><span class="line"> {</span><br><span class="line"> ptrace(PTRACE_TRACEME, <span class="number">0</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line"> execl(<span class="string">"/bin/ls"</span>, <span class="string">"ls"</span>, <span class="literal">NULL</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">long</span> orig_eax;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">char</span> *str, *laddr;</span><br><span class="line"> <span class="keyword">int</span> toggle = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span> (<span class="number">1</span>)</span><br><span class="line"> {</span><br><span class="line"> wait(&status);</span><br><span class="line"> <span class="keyword">if</span> (WIFEXITED(status))</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> orig_eax = ptrace(PTRACE_PEEKUSER, child, <span class="number">8</span> * ORIG_RAX, <span class="literal">NULL</span>);</span><br><span class="line"> <span class="keyword">if</span> (orig_eax == SYS_write)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (toggle == <span class="number">0</span>)</span><br><span class="line"> {</span><br><span class="line"> toggle = <span class="number">1</span>;</span><br><span class="line"> ptrace(PTRACE_GETREGS, child, <span class="literal">NULL</span>, &regs);</span><br><span class="line"></span><br><span class="line"> str = (<span class="keyword">char</span> *)<span class="built_in">calloc</span>((regs.rdx + <span class="number">1</span>), <span class="keyword">sizeof</span>(<span class="keyword">char</span>));</span><br><span class="line"> getdata(child, regs.rsi, str, regs.rdx);</span><br><span class="line"> reverse(str);</span><br><span class="line"> putdata(child, regs.rsi, str, regs.rdx);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> toggle = <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> ptrace(PTRACE_SYSCALL, child, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>结果<br><img src="https://i.loli.net/2019/08/14/H5jefxws6g3h2io.png" alt> </p>
<h2 id="向其它程序注入指令"><a href="#向其它程序注入指令" class="headerlink" title="向其它程序注入指令"></a>向其它程序注入指令</h2><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ptrace(PTRACE_ATTACH, pid, <span class="literal">NULL</span>, <span class="literal">NULL</span>)</span><br></pre></td></tr></table></figure>
<p><img src="https://i.loli.net/2019/08/14/aWvUMpZ8nfzT64s.png" alt><br>使<code>pid</code>进程成为被追踪的<code>tracee</code>进程。<code>tracee</code>进程会被发送一个<code>SIGTOP</code>信号量,<code>tracee</code>进程不会立即停止,直到完成本次系统调用。如果要结束追踪,则调用<code>PTRACE_DETACH</code>即可。</p>
<p><code>debug</code> 设置断点的功能可以通过<code>ptrace</code>实现。原理是<code>ATTACH</code>正在运行的进程使其停止。然后读取该进程的指令寄存器<code>IR</code>(32位x86为<code>EIP</code>,64位的是<code>RIP</code>)内容所指向的指令,备份后替换成目标指令,再使其继续执行,此时被追踪进程就会执行我们替换的指令,运行完注入的指令之后,我们再恢复原进程的<code>IR</code><br>,从而达到改变原程序运行逻辑的目的。</p>
<figure class="highlight c"><figcaption><span>tracee</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><unistd.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">int</span> i=<span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span>(<span class="number">1</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"Hello,ptrace! [pid:%d]! num is %d\n"</span>,getpid(),i++);</span><br><span class="line"> sleep(<span class="number">2</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight c"><figcaption><span>tracer</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/ptrace.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/reg.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/wait.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/user.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdlib.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><errno.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><string.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> long_size sizeof(long)</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">getdata</span><span class="params">(<span class="keyword">pid_t</span> child, <span class="keyword">long</span> addr, <span class="keyword">char</span> *str, <span class="keyword">int</span> len)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">char</span> *laddr = str;</span><br><span class="line"> <span class="keyword">int</span> i, j;</span><br><span class="line"> <span class="keyword">union</span> u {</span><br><span class="line"> <span class="keyword">long</span> val;</span><br><span class="line"> <span class="keyword">char</span> chars[long_size];</span><br><span class="line"> } data;</span><br><span class="line"> i = <span class="number">0</span>;</span><br><span class="line"> j = len / long_size;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span> (i < j)</span><br><span class="line"> {</span><br><span class="line"> data.val = ptrace(PTRACE_PEEKDATA, child, addr + long_size * i, <span class="literal">NULL</span>);</span><br><span class="line"> <span class="keyword">if</span> (data.val == <span class="number">-1</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (errno)</span><br><span class="line"> {</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"READ error: %s\n"</span>, strerror(errno));</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">memcpy</span>(laddr, data.chars, long_size);</span><br><span class="line"> ++i;</span><br><span class="line"> laddr = laddr + long_size;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> j = len % long_size;</span><br><span class="line"> <span class="keyword">if</span> (j != <span class="number">0</span>)</span><br><span class="line"> {</span><br><span class="line"> data.val = ptrace(PTRACE_PEEKDATA, child, addr + long_size * i, <span class="literal">NULL</span>);</span><br><span class="line"> <span class="keyword">if</span> (data.val == <span class="number">-1</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (errno)</span><br><span class="line"> {</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"READ error: %s\n"</span>, strerror(errno));</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">memcpy</span>(laddr, data.chars, j);</span><br><span class="line"> }</span><br><span class="line"> str[len] = <span class="string">'\0'</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">putdata</span><span class="params">(<span class="keyword">pid_t</span> child, <span class="keyword">long</span> addr, <span class="keyword">char</span> *str, <span class="keyword">int</span> len)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">char</span> *laddr = str;</span><br><span class="line"> <span class="keyword">int</span> i, j;</span><br><span class="line"> j = len / long_size;</span><br><span class="line"> i = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">union</span> u {</span><br><span class="line"> <span class="keyword">long</span> val;</span><br><span class="line"> <span class="keyword">char</span> chars[long_size];</span><br><span class="line"> } data;</span><br><span class="line"> <span class="keyword">while</span> (i < j)</span><br><span class="line"> {</span><br><span class="line"> <span class="built_in">memcpy</span>(data.chars, laddr, long_size);</span><br><span class="line"> ptrace(PTRACE_POKEDATA, child, addr + long_size * i, data.val);</span><br><span class="line"> ++i;</span><br><span class="line"> laddr = laddr + long_size;</span><br><span class="line"> }</span><br><span class="line"> j = len % long_size;</span><br><span class="line"> <span class="keyword">if</span> (j != <span class="number">0</span>)</span><br><span class="line"> {</span><br><span class="line"> data.val = ptrace(PTRACE_PEEKDATA, child, addr + long_size * i, <span class="literal">NULL</span>);</span><br><span class="line"> <span class="keyword">if</span> (data.val == <span class="number">-1</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (errno)</span><br><span class="line"> {</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"READ error: %s\n"</span>, strerror(errno));</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="built_in">memcpy</span>(data.chars, laddr, j);</span><br><span class="line"> ptrace(PTRACE_POKEDATA, child, addr + long_size * i, data.val);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span> *argv[])</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">if</span> (argc != <span class="number">2</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"Usage: %s pid\n"</span>, argv[<span class="number">0</span>]);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">pid_t</span> tracee = atoi(argv[<span class="number">1</span>]);</span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">user_regs_struct</span> <span class="title">regs</span>;</span></span><br><span class="line"> <span class="comment">/*int 80(系统调用) int 3(断点)*/</span></span><br><span class="line"> <span class="keyword">unsigned</span> <span class="keyword">char</span> code[] = {<span class="number">0xcd</span>, <span class="number">0x80</span>, <span class="number">0xcc</span>, <span class="number">0x00</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>}; <span class="comment">//八个字节,等于long 型的长度</span></span><br><span class="line"> <span class="keyword">char</span> backup[<span class="number">8</span>]; <span class="comment">//备份读取的指令</span></span><br><span class="line"> ptrace(PTRACE_ATTACH, tracee, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line"> <span class="keyword">long</span> inst; <span class="comment">//用于保存指令寄存器所指向的下一条将要执行的指令的内存地址</span></span><br><span class="line"></span><br><span class="line"> wait(<span class="literal">NULL</span>);</span><br><span class="line"> ptrace(PTRACE_GETREGS, tracee, <span class="literal">NULL</span>, &regs);</span><br><span class="line"> inst = ptrace(PTRACE_PEEKTEXT, tracee, regs.rip, <span class="literal">NULL</span>);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"tracee:RIP:0x%llx INST: 0x%lx\n"</span>, regs.rip, inst);</span><br><span class="line"> <span class="comment">//读取子进程将要执行的 7 bytes指令并备份</span></span><br><span class="line"> getdata(tracee, regs.rip, backup, <span class="number">7</span>);</span><br><span class="line"> <span class="comment">//设置断点</span></span><br><span class="line"> putdata(tracee, regs.rip, code, <span class="number">7</span>);</span><br><span class="line"> <span class="comment">//让子进程继续执行并执行“int 3”断点指令停止</span></span><br><span class="line"> ptrace(PTRACE_CONT, tracee, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line"> wait(<span class="literal">NULL</span>);</span><br><span class="line"> <span class="keyword">long</span> rip = ptrace(PTRACE_PEEKUSER, tracee, <span class="number">8</span> * RIP, <span class="literal">NULL</span>); <span class="comment">//获取子进程停止时,rip的值</span></span><br><span class="line"> <span class="keyword">long</span> inst2 = ptrace(PTRACE_PEEKTEXT, tracee, rip, <span class="literal">NULL</span>);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"tracee:RIP:0x%lx INST: 0x%lx\n"</span>, rip, inst2);</span><br><span class="line"></span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"Press Enter to continue tracee process\n"</span>);</span><br><span class="line"> getchar();</span><br><span class="line"> putdata(tracee, regs.rip, backup, <span class="number">7</span>); <span class="comment">//重新将备份的指令写回寄存器</span></span><br><span class="line"> ptrace(PTRACE_SETREGS, tracee, <span class="literal">NULL</span>, &regs); <span class="comment">//设置会原来的寄存器值</span></span><br><span class="line"> ptrace(PTRACE_CONT, tracee, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line"> ptrace(PTRACE_DETACH, tracee, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>结果<br><img src="https://i.loli.net/2019/08/14/xqY1XHKJTCQWuet.png" alt><br>在运行<code>ptracer</code>后<code>ptracee</code>被插入一个<code>int 3</code>断点</p>
<p><strong>注意:<code>ptracer</code>应在<code>root</code>权限下运行</strong></p>
<h1 id="附录"><a href="#附录" class="headerlink" title="附录"></a>附录</h1><h2 id="不同平台的系统调用方式"><a href="#不同平台的系统调用方式" class="headerlink" title="不同平台的系统调用方式"></a>不同平台的系统调用方式</h2><p><img src="https://i.loli.net/2019/08/14/KyZ5oX2nIt9EVuG.png" alt="不同平台的系统调用方式"></p>
<h2 id="不同平台使用的参数寄存器"><a href="#不同平台使用的参数寄存器" class="headerlink" title="不同平台使用的参数寄存器"></a>不同平台使用的参数寄存器</h2><p><img src="https://i.loli.net/2019/08/14/ifrTU6M3X2gocPw.png" alt="不同平台使用的参数寄存器"></p>
<h1 id="参考文档"><a href="#参考文档" class="headerlink" title="参考文档"></a>参考文档</h1><p><a href="http://man7.org/linux/man-pages/man2/syscall.2.html" target="_blank" rel="noopener">http://man7.org/linux/man-pages/man2/syscall.2.html</a><br><a href="http://man7.org/linux/man-pages/man2/ptrace.2.html" target="_blank" rel="noopener">http://man7.org/linux/man-pages/man2/ptrace.2.html</a><br><a href="https://blog.csdn.net/u012417380/article/details/60470075" target="_blank" rel="noopener">https://blog.csdn.net/u012417380/article/details/60470075</a></p>
</div>
<footer class="post-footer">
<div class="post-tags">
<a href="/tags/C/" rel="tag"># C</a>
<a href="/tags/hook/" rel="tag"># hook</a>
</div>
<div class="post-nav">
<div class="post-nav-next post-nav-item">
<a href="/fork函数.html" rel="next" title="fork函数">
<i class="fa fa-chevron-left"></i> fork函数
</a>
</div>
<span class="post-nav-divider"></span>
<div class="post-nav-prev post-nav-item">
<a href="/一次基于Socket通信的App的分析.html" rel="prev" title="一次基于Socket通信的App的分析">
一次基于Socket通信的App的分析 <i class="fa fa-chevron-right"></i>
</a>
</div>
</div>
</footer>
</div>
</article>
</div>
</div>
<div class="comments" id="gitalk-container"></div>
</div>
<div class="sidebar-toggle">
<div class="sidebar-toggle-line-wrap">
<span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
<span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
<span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
</div>
</div>
<aside id="sidebar" class="sidebar">
<div class="sidebar-inner">
<ul class="sidebar-nav motion-element">
<li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
文章目录
</li>
<li class="sidebar-nav-overview" data-target="site-overview-wrap">
站点概览
</li>
</ul>
<div class="site-overview-wrap sidebar-panel">
<div class="site-overview">
<div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
<img class="site-author-image" itemprop="image"
src="/images/headicon.png"
alt="0xE4s0n">
<p class="site-author-name" itemprop="name">0xE4s0n</p>
<div class="site-description motion-element" itemprop="description"></div>
</div>
<nav class="site-state motion-element">
<div class="site-state-item site-state-posts">
<a href="/archives/">
<span class="site-state-item-count">8</span>
<span class="site-state-item-name">日志</span>
</a>
</div>
<div class="site-state-item site-state-categories">
<a href="/categories/">
<span class="site-state-item-count">3</span>
<span class="site-state-item-name">分类</span>
</a>
</div>
<div class="site-state-item site-state-tags">
<a href="/tags/">
<span class="site-state-item-count">4</span>
<span class="site-state-item-name">标签</span>
</a>
</div>
</nav>
<div class="feed-link motion-element">
<a href="/atom.xml" rel="alternate">
<i class="fa fa-rss"></i>RSS
</a>
</div>
<div class="links-of-blogroll motion-element links-of-blogroll-block">
<div class="links-of-blogroll-title">
<i class="fa fa-fw fa-link"></i>
友链
</div>
<ul class="links-of-blogroll-list">
<li class="links-of-blogroll-item">
<a href="https://syc-2019--fxxy.repl.co" title="https://syc-2019--fxxy.repl.co" rel="noopener" target="_blank">Syclover</a>
</li>
<li class="links-of-blogroll-item">
<a href="https://www.0xpoker.cn/" title="https://www.0xpoker.cn/" rel="noopener" target="_blank">0xpoker</a>
</li>
<li class="links-of-blogroll-item">
<a href="https://fingerprint.bitcron.com/" title="https://fingerprint.bitcron.com/" rel="noopener" target="_blank">0x指纹</a>
</li>
<li class="links-of-blogroll-item">
<a href="http://www.reversing.win/" title="http://www.reversing.win/" rel="noopener" target="_blank">0x7o8v</a>
</li>
<li class="links-of-blogroll-item">
<a href="https://zoniony.github.io/" title="https://zoniony.github.io/" rel="noopener" target="_blank">zoniony</a>
</li>
<li class="links-of-blogroll-item">
<a href="https://abcdefghijklmnopqrst.xyz/" title="https://abcdefghijklmnopqrst.xyz/" rel="noopener" target="_blank">骑麦兜看日落</a>
</li>
</ul>
</div>
</div>
</div>
<!--noindex-->
<div class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
<div class="post-toc">
<div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#ptrace-函数简介"><span class="nav-number">1.</span> <span class="nav-text">ptrace 函数简介</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#函数原型"><span class="nav-number">1.1.</span> <span class="nav-text">函数原型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#参数意义"><span class="nav-number">1.2.</span> <span class="nav-text">参数意义</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#描述"><span class="nav-number">1.3.</span> <span class="nav-text">描述</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#示例"><span class="nav-number">2.</span> <span class="nav-text">示例</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#追踪系统调用号"><span class="nav-number">2.1.</span> <span class="nav-text">追踪系统调用号</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#系统调用"><span class="nav-number">2.1.1.</span> <span class="nav-text">系统调用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#开始追踪"><span class="nav-number">2.1.2.</span> <span class="nav-text">开始追踪</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#读取系统调用参数"><span class="nav-number">2.2.</span> <span class="nav-text">读取系统调用参数</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#修改子进程系统调用参数"><span class="nav-number">2.3.</span> <span class="nav-text">修改子进程系统调用参数</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#向其它程序注入指令"><span class="nav-number">2.4.</span> <span class="nav-text">向其它程序注入指令</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#附录"><span class="nav-number">3.</span> <span class="nav-text">附录</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#不同平台的系统调用方式"><span class="nav-number">3.1.</span> <span class="nav-text">不同平台的系统调用方式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#不同平台使用的参数寄存器"><span class="nav-number">3.2.</span> <span class="nav-text">不同平台使用的参数寄存器</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#参考文档"><span class="nav-number">4.</span> <span class="nav-text">参考文档</span></a></li></ol></div>
</div>
</div>
<!--/noindex-->
<div class="back-to-top motion-element">
<i class="fa fa-arrow-up"></i>
<span id="scrollpercent"><span>0</span>%</span>
</div>
</div>
</aside>
<div id="sidebar-dimmer"></div>
</div>
</main>
<footer id="footer" class="footer">
<div class="footer-inner">
<div class="copyright">© <span itemprop="copyrightYear">2021</span>
<span class="with-love" id="animate">
<i class="fa fa-user"></i>
</span>
<span class="author" itemprop="copyrightHolder">0xE4s0n</span>
</div>
<div id="days"></div>
<script>
function show_date_time(){
window.setTimeout("show_date_time()", 1000);
BirthDay=new Date("06/17/2019 15:13:14");//修改为自己的blog建站时间
today=new Date();
timeold=(today.getTime()-BirthDay.getTime());
sectimeold=timeold/1000
secondsold=Math.floor(sectimeold);
msPerDay=24*60*60*1000
e_daysold=timeold/msPerDay
daysold=Math.floor(e_daysold);
e_hrsold=(e_daysold-daysold)*24;
hrsold=setzero(Math.floor(e_hrsold));
e_minsold=(e_hrsold-hrsold)*60;
minsold=setzero(Math.floor((e_hrsold-hrsold)*60));
seconds=setzero(Math.floor((e_minsold-minsold)*60));
document.getElementById('days').innerHTML="已运行"+daysold+"天"+hrsold+"小时"+minsold+"分"+seconds+"秒";
}
function setzero(i){
if (i<10)
{i="0" + i};
return i;
}
show_date_time();
</script>
<div class="busuanzi-count">
<script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<span class="post-meta-item-icon">
<i class="fa fa-user"></i>
</span>
<span class="site-uv" title="总访客量">
访客:<span class="busuanzi-value" id="busuanzi_value_site_uv"></span>
</span>
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-eye"></i>
</span>
<span class="site-pv" title="总访问量">
浏览次数:<span class="busuanzi-value" id="busuanzi_value_site_pv"></span>
</span>
</div>
</div>
</footer>
</div>
<script color='0,0,255' opacity='0.5' zIndex='-1' count='99' src="//cdn.bootcss.com/canvas-nest.js/1.0.1/canvas-nest.min.js"></script>
<script src="//cdn.jsdelivr.net/jquery/2.1.3/jquery.min.js"></script>
<script src="//cdn.jsdelivr.net/fancybox/2.1.5/jquery.fancybox.pack.js"></script>
<script defer src="/lib/three/three.min.js"></script>
<script defer src="/lib/three/canvas_sphere.min.js"></script>
<script src="/js/utils.js?v=7.2.0"></script>
<script src="/js/affix.js?v=7.2.0"></script>
<script src="/js/schemes/pisces.js?v=7.2.0"></script>
<script src="/js/scrollspy.js?v=7.2.0"></script>
<script src="/js/post-details.js?v=7.2.0"></script>
<script src="/js/next-boot.js?v=7.2.0"></script>
<script>
(function(){
var bp = document.createElement('script');
var curProtocol = window.location.protocol.split(':')[0];
bp.src = (curProtocol === 'https') ? 'https://zz.bdstatic.com/linksubmit/push.js' : 'http://push.zhanzhang.baidu.com/push.js';
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(bp, s);
})();
</script>
<script src="//cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.js"></script>
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.css">
<script src="//cdn.jsdelivr.net/npm/[email protected]/src/md5.min.js"></script>
<script>
var gitalk = new Gitalk({
clientID: '20a66d45deddc86a7b8f',
clientSecret: 'e7f74883281913b8ce00b761fcd7b79f844e4d4d',
repo: '0xE4s0n.github.io',
owner: '0xE4s0n',
admin: ['0xE4s0n'],
id: md5(location.pathname),
language: 'zh-CN',
distractionFreeMode: 'true'
});
gitalk.render('gitalk-container');
</script>
<script src="/live2d-widget/autoload.js"></script>
</body>
</html>