debugger(一):打斷點的實現以及案例分析

〇、前言

最近在學習 debugger 的實現原理,并按照博客實現,是一個很不錯的小項目,這是地址。由于 macOS 的問題,系統調用并不完全相同,因此實現了兩個版本分支,一個是 main 版本分支(macOS M1 silicon),另一個是 linux 版本分支(Ubuntu 20.04 x86),這是倉庫地址。以下以及后都用 linux 版本代碼闡述其原理。

一、斷點創建

這很簡單,主要是由 ptrace() 實現(debug工具都依賴于 ptrace() ):

#ifndef BREAKPOINT_HPP_
#define BREAKPOINT_HPP_
#include <stdint.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
class BreakPoint {pid_t m_pid;intptr_t m_addr;bool m_enabled;uint8_t m_saved_data; // 最低位的舊數據(1 字節),之后需要恢復public:BreakPoint() {}BreakPoint(pid_t pid, intptr_t addr): m_pid(pid), m_addr(addr), m_enabled(false), m_saved_data{} {}auto is_enabled() const -> bool { return m_enabled; }auto get_address() const -> intptr_t { return m_addr; }void enable() {auto data = ptrace(PTRACE_PEEKDATA, m_pid, m_addr, nullptr);m_saved_data = static_cast<uint8_t>(data & 0xff); // save bottom byteuint64_t int3 = 0xcc;uint64_t data_with_int3 = ((data & ~0xff) | int3); // set bottom byte to// 0xccptrace(PTRACE_POKEDATA, m_pid, m_addr, data_with_int3);m_enabled = true;}void disable() {auto data = ptrace(PTRACE_PEEKDATA, m_pid, m_addr, nullptr);auto restored_data = ((data & ~0xff) | m_saved_data);ptrace(PTRACE_POKEDATA, m_pid, m_addr, restored_data);m_enabled = false;}
};
#endif

以上是 BreakPoint 類的定義。重點是關注 enable()disable() 兩個方法,在這兩個方法中,這段代碼及其關鍵:

	auto data = ptrace(PTRACE_PEEKDATA, m_pid, m_addr, nullptr);m_saved_data = static_cast<uint8_t>(data & 0xff); // save bottom byteuint64_t int3 = 0xcc;uint64_t data_with_int3 = ((data & ~0xff) | int3); // set bottom byte to// 0xccptrace(PTRACE_POKEDATA, m_pid, m_addr, data_with_int3);

這里先說明一下,int3x86 中的一個中斷指令,只要我們把某個指令修改為 int3,那么它運行到這里就會停下來。另外,我們只是打個斷點,又不想真正得越過這個指令(這個指令被越過不執行,誰都不知道會發生什么),所以后面得恢復這個執行,并重新執行它,這就是 disable(),我們先討論 enable()

因為 int3 指令的代碼為 0xcc,這很明顯是一個 1 字節指令,只要我們在我們想打斷的指令處,將操作碼改為 0xcc,這個指令就會停下來(這里牽扯到字節序,因為指令第一個字節是低地址,因為我們需要將 int3 放在一個指令的最低處)。然后再將這個被篡改的指令放回到原處,就成功的打了一個斷點。

至于 disable(),其實做的也是這樣的事情,將原來的被替換的一個字節再恢復放回去:

	auto data = ptrace(PTRACE_PEEKDATA, m_pid, m_addr, nullptr);auto restored_data = ((data & ~0xff) | m_saved_data);ptrace(PTRACE_POKEDATA, m_pid, m_addr, restored_data);m_enabled = false;

以上都是很簡單的東西,我們現在就可以檢驗這個事情了,對了以下是 debugger 類的定義:

#ifndef DEBUGGER_HPP_
#define DEBUGGER_HPP_#include "../ext/linenoise/linenoise.h"
#include "breakpoint.hpp"
#include "helpers.hpp"
#include <cstddef>
#include <iostream>
#include <string>
#include <unordered_map>class debugger {std::string m_prog_name;pid_t m_pid;std::unordered_map<std::intptr_t, BreakPoint> m_breakPoints; // 存儲斷點public:// 這里不應該給默認參數,斷言:傳了正確的 prog_name,piddebugger(std::string prog_name, pid_t pid): m_prog_name(prog_name), m_pid(pid) {}void run() {int wait_status;auto options = 0;waitpid(m_pid, &wait_status, options);char *line = nullptr;while ((line = linenoise("minidbg> ")) != nullptr) {handl_command(line);linenoiseHistoryAdd(line);linenoiseFree(line);}}// handlersvoid handl_command(const std::string &line) {auto args = split(line, ' ');auto command = args[0];if (is_prefix(command, "continue")) {continue_execution();} else if (is_prefix(command, "break")) { // break 地址std::string addr{args[1], 2};set_breakPoint(std::stol(addr, 0, 16));} else {std::cerr << "Unkown command\n";}}void continue_execution() {ptrace(PTRACE_CONT, m_pid, nullptr, nullptr);int wait_status;auto options = 0;waitpid(m_pid, &wait_status, options);}void set_breakPoint(std::intptr_t addr) {std::cout << "Set breakpoint at address 0x" << std::hex << addr<< std::endl;BreakPoint bp{m_pid, addr};bp.enable();m_breakPoints[addr] = bp;}~debugger() {}
};#endif

二、檢測

main() 就是 debuggermain() 了:

#include "../include/debugger.hpp"
#include <cstddef>
#include <iostream>
#include <unistd.h>
#include <sys/personality.h>
int main(int argc, char *argv[]) {if (argc < 2) {std::cerr << "Program paras are not right.";return -1;}auto proj = argv[1];auto pid = fork();if (pid == 0) {personality(ADDR_NO_RANDOMIZE); // 取消隨機內存// child progress// debugged progressptrace(PTRACE_TRACEME, 0, nullptr, nullptr);execl(proj, proj, nullptr);} else if (pid >= 1) {// parent progress// debugger progressstd::cout << "Start debugging the progress: " << proj << ", pid = " << pid<< ":\n";debugger dbg(proj, pid);dbg.run();}return 0;
}

被 debug 的進程放在子進程中,然后由父進程,也就是我們的 debugger process,由它進行調試。

我們先寫一個被 debug 的程序,這個程序輸出 hello,world.

#include <iostream>
int main() {std::cerr << "hello,world.\n";return 0;
}

編譯后,我們要打斷點進行測試,可以看到目前只能傳入一個地址,這個地址還是 0x 開頭的 16 進制地址,我們對于這個地址絲毫沒有頭緒,因為我們不知道 std::cerr << "hello,world.\n";這個語句對應的匯編代碼的指令地址是什么。這個程序首先有一個程序結構,對這個不清楚的話,可以看看我之前寫的文章,是關于 elf 的,可以參考 c++ 內存模型或者 c++內存管理的那幾篇博客。

現在看看這個被調試的程序的文件結構:

objdump -d hw        hw:     file format elf64-x86-64Disassembly of section .init:0000000000001000 <_init>:1000:       f3 0f 1e fa             endbr64 1004:       48 83 ec 08             sub    $0x8,%rsp1008:       48 8b 05 d9 2f 00 00    mov    0x2fd9(%rip),%rax        # 3fe8 <__gmon_start__>100f:       48 85 c0                test   %rax,%rax1012:       74 02                   je     1016 <_init+0x16>1014:       ff d0                   callq  *%rax1016:       48 83 c4 08             add    $0x8,%rsp101a:       c3                      retq   Disassembly of section .plt:0000000000001020 <.plt>:1020:       ff 35 82 2f 00 00       pushq  0x2f82(%rip)        # 3fa8 <_GLOBAL_OFFSET_TABLE_+0x8>1026:       f2 ff 25 83 2f 00 00    bnd jmpq *0x2f83(%rip)        # 3fb0 <_GLOBAL_OFFSET_TABLE_+0x10>102d:       0f 1f 00                nopl   (%rax)1030:       f3 0f 1e fa             endbr64 1034:       68 00 00 00 00          pushq  $0x01039:       f2 e9 e1 ff ff ff       bnd jmpq 1020 <.plt>103f:       90                      nop1040:       f3 0f 1e fa             endbr64 1044:       68 01 00 00 00          pushq  $0x11049:       f2 e9 d1 ff ff ff       bnd jmpq 1020 <.plt>104f:       90                      nop1050:       f3 0f 1e fa             endbr64 1054:       68 02 00 00 00          pushq  $0x21059:       f2 e9 c1 ff ff ff       bnd jmpq 1020 <.plt>105f:       90                      nopDisassembly of section .plt.got:0000000000001060 <__cxa_finalize@plt>:1060:       f3 0f 1e fa             endbr64 1064:       f2 ff 25 65 2f 00 00    bnd jmpq *0x2f65(%rip)        # 3fd0 <__cxa_finalize@GLIBC_2.2.5>106b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)Disassembly of section .plt.sec:0000000000001070 <__cxa_atexit@plt>:1070:       f3 0f 1e fa             endbr64 1074:       f2 ff 25 3d 2f 00 00    bnd jmpq *0x2f3d(%rip)        # 3fb8 <__cxa_atexit@GLIBC_2.2.5>107b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)0000000000001080 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>:1080:       f3 0f 1e fa             endbr64 1084:       f2 ff 25 35 2f 00 00    bnd jmpq *0x2f35(%rip)        # 3fc0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@GLIBCXX_3.4>108b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)0000000000001090 <_ZNSt8ios_base4InitC1Ev@plt>:1090:       f3 0f 1e fa             endbr64 1094:       f2 ff 25 2d 2f 00 00    bnd jmpq *0x2f2d(%rip)        # 3fc8 <_ZNSt8ios_base4InitC1Ev@GLIBCXX_3.4>109b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)Disassembly of section .text:00000000000010a0 <_start>:10a0:       f3 0f 1e fa             endbr64 10a4:       31 ed                   xor    %ebp,%ebp10a6:       49 89 d1                mov    %rdx,%r910a9:       5e                      pop    %rsi10aa:       48 89 e2                mov    %rsp,%rdx10ad:       48 83 e4 f0             and    $0xfffffffffffffff0,%rsp10b1:       50                      push   %rax10b2:       54                      push   %rsp10b3:       4c 8d 05 d6 01 00 00    lea    0x1d6(%rip),%r8        # 1290 <__libc_csu_fini>10ba:       48 8d 0d 5f 01 00 00    lea    0x15f(%rip),%rcx        # 1220 <__libc_csu_init>10c1:       48 8d 3d c1 00 00 00    lea    0xc1(%rip),%rdi        # 1189 <main>10c8:       ff 15 12 2f 00 00       callq  *0x2f12(%rip)        # 3fe0 <__libc_start_main@GLIBC_2.2.5>10ce:       f4                      hlt    10cf:       90                      nop00000000000010d0 <deregister_tm_clones>:10d0:       48 8d 3d 39 2f 00 00    lea    0x2f39(%rip),%rdi        # 4010 <__TMC_END__>10d7:       48 8d 05 32 2f 00 00    lea    0x2f32(%rip),%rax        # 4010 <__TMC_END__>10de:       48 39 f8                cmp    %rdi,%rax10e1:       74 15                   je     10f8 <deregister_tm_clones+0x28>10e3:       48 8b 05 ee 2e 00 00    mov    0x2eee(%rip),%rax        # 3fd8 <_ITM_deregisterTMCloneTable>10ea:       48 85 c0                test   %rax,%rax10ed:       74 09                   je     10f8 <deregister_tm_clones+0x28>10ef:       ff e0                   jmpq   *%rax10f1:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)10f8:       c3                      retq   10f9:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)0000000000001100 <register_tm_clones>:1100:       48 8d 3d 09 2f 00 00    lea    0x2f09(%rip),%rdi        # 4010 <__TMC_END__>1107:       48 8d 35 02 2f 00 00    lea    0x2f02(%rip),%rsi        # 4010 <__TMC_END__>110e:       48 29 fe                sub    %rdi,%rsi1111:       48 89 f0                mov    %rsi,%rax1114:       48 c1 ee 3f             shr    $0x3f,%rsi1118:       48 c1 f8 03             sar    $0x3,%rax111c:       48 01 c6                add    %rax,%rsi111f:       48 d1 fe                sar    %rsi1122:       74 14                   je     1138 <register_tm_clones+0x38>1124:       48 8b 05 c5 2e 00 00    mov    0x2ec5(%rip),%rax        # 3ff0 <_ITM_registerTMCloneTable>112b:       48 85 c0                test   %rax,%rax112e:       74 08                   je     1138 <register_tm_clones+0x38>1130:       ff e0                   jmpq   *%rax1132:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)1138:       c3                      retq   1139:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)0000000000001140 <__do_global_dtors_aux>:1140:       f3 0f 1e fa             endbr64 1144:       80 3d e5 2f 00 00 00    cmpb   $0x0,0x2fe5(%rip)        # 4130 <completed.0>114b:       75 2b                   jne    1178 <__do_global_dtors_aux+0x38>114d:       55                      push   %rbp114e:       48 83 3d 7a 2e 00 00    cmpq   $0x0,0x2e7a(%rip)        # 3fd0 <__cxa_finalize@GLIBC_2.2.5>1155:       00 1156:       48 89 e5                mov    %rsp,%rbp1159:       74 0c                   je     1167 <__do_global_dtors_aux+0x27>115b:       48 8b 3d a6 2e 00 00    mov    0x2ea6(%rip),%rdi        # 4008 <__dso_handle>1162:       e8 f9 fe ff ff          callq  1060 <__cxa_finalize@plt>1167:       e8 64 ff ff ff          callq  10d0 <deregister_tm_clones>116c:       c6 05 bd 2f 00 00 01    movb   $0x1,0x2fbd(%rip)        # 4130 <completed.0>1173:       5d                      pop    %rbp1174:       c3                      retq   1175:       0f 1f 00                nopl   (%rax)1178:       c3                      retq   1179:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)0000000000001180 <frame_dummy>:1180:       f3 0f 1e fa             endbr64 1184:       e9 77 ff ff ff          jmpq   1100 <register_tm_clones>0000000000001189 <main>:1189:       f3 0f 1e fa             endbr64 118d:       55                      push   %rbp118e:       48 89 e5                mov    %rsp,%rbp1191:       48 8d 35 6d 0e 00 00    lea    0xe6d(%rip),%rsi        # 2005 <_ZStL19piecewise_construct+0x1>1198:       48 8d 3d 81 2e 00 00    lea    0x2e81(%rip),%rdi        # 4020 <_ZSt4cerr@@GLIBCXX_3.4>119f:       e8 dc fe ff ff          callq  1080 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>11a4:       b8 00 00 00 00          mov    $0x0,%eax11a9:       5d                      pop    %rbp11aa:       c3                      retq   00000000000011ab <_Z41__static_initialization_and_destruction_0ii>:11ab:       f3 0f 1e fa             endbr64 11af:       55                      push   %rbp11b0:       48 89 e5                mov    %rsp,%rbp11b3:       48 83 ec 10             sub    $0x10,%rsp11b7:       89 7d fc                mov    %edi,-0x4(%rbp)11ba:       89 75 f8                mov    %esi,-0x8(%rbp)11bd:       83 7d fc 01             cmpl   $0x1,-0x4(%rbp)11c1:       75 32                   jne    11f5 <_Z41__static_initialization_and_destruction_0ii+0x4a>11c3:       81 7d f8 ff ff 00 00    cmpl   $0xffff,-0x8(%rbp)11ca:       75 29                   jne    11f5 <_Z41__static_initialization_and_destruction_0ii+0x4a>11cc:       48 8d 3d 5e 2f 00 00    lea    0x2f5e(%rip),%rdi        # 4131 <_ZStL8__ioinit>11d3:       e8 b8 fe ff ff          callq  1090 <_ZNSt8ios_base4InitC1Ev@plt>11d8:       48 8d 15 29 2e 00 00    lea    0x2e29(%rip),%rdx        # 4008 <__dso_handle>11df:       48 8d 35 4b 2f 00 00    lea    0x2f4b(%rip),%rsi        # 4131 <_ZStL8__ioinit>11e6:       48 8b 05 0b 2e 00 00    mov    0x2e0b(%rip),%rax        # 3ff8 <_ZNSt8ios_base4InitD1Ev@GLIBCXX_3.4>11ed:       48 89 c7                mov    %rax,%rdi11f0:       e8 7b fe ff ff          callq  1070 <__cxa_atexit@plt>11f5:       90                      nop11f6:       c9                      leaveq 11f7:       c3                      retq   00000000000011f8 <_GLOBAL__sub_I_main>:11f8:       f3 0f 1e fa             endbr64 11fc:       55                      push   %rbp11fd:       48 89 e5                mov    %rsp,%rbp1200:       be ff ff 00 00          mov    $0xffff,%esi1205:       bf 01 00 00 00          mov    $0x1,%edi120a:       e8 9c ff ff ff          callq  11ab <_Z41__static_initialization_and_destruction_0ii>120f:       5d                      pop    %rbp1210:       c3                      retq   1211:       66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)1218:       00 00 00 121b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)0000000000001220 <__libc_csu_init>:1220:       f3 0f 1e fa             endbr64 1224:       41 57                   push   %r151226:       4c 8d 3d 5b 2b 00 00    lea    0x2b5b(%rip),%r15        # 3d88 <__frame_dummy_init_array_entry>122d:       41 56                   push   %r14122f:       49 89 d6                mov    %rdx,%r141232:       41 55                   push   %r131234:       49 89 f5                mov    %rsi,%r131237:       41 54                   push   %r121239:       41 89 fc                mov    %edi,%r12d123c:       55                      push   %rbp123d:       48 8d 2d 54 2b 00 00    lea    0x2b54(%rip),%rbp        # 3d98 <__do_global_dtors_aux_fini_array_entry>1244:       53                      push   %rbx1245:       4c 29 fd                sub    %r15,%rbp1248:       48 83 ec 08             sub    $0x8,%rsp124c:       e8 af fd ff ff          callq  1000 <_init>1251:       48 c1 fd 03             sar    $0x3,%rbp1255:       74 1f                   je     1276 <__libc_csu_init+0x56>1257:       31 db                   xor    %ebx,%ebx1259:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)1260:       4c 89 f2                mov    %r14,%rdx1263:       4c 89 ee                mov    %r13,%rsi1266:       44 89 e7                mov    %r12d,%edi1269:       41 ff 14 df             callq  *(%r15,%rbx,8)126d:       48 83 c3 01             add    $0x1,%rbx1271:       48 39 dd                cmp    %rbx,%rbp1274:       75 ea                   jne    1260 <__libc_csu_init+0x40>1276:       48 83 c4 08             add    $0x8,%rsp127a:       5b                      pop    %rbx127b:       5d                      pop    %rbp127c:       41 5c                   pop    %r12127e:       41 5d                   pop    %r131280:       41 5e                   pop    %r141282:       41 5f                   pop    %r151284:       c3                      retq   1285:       66 66 2e 0f 1f 84 00    data16 nopw %cs:0x0(%rax,%rax,1)128c:       00 00 00 00 0000000000001290 <__libc_csu_fini>:1290:       f3 0f 1e fa             endbr64 1294:       c3                      retq   Disassembly of section .fini:0000000000001298 <_fini>:1298:       f3 0f 1e fa             endbr64 129c:       48 83 ec 08             sub    $0x8,%rsp12a0:       48 83 c4 08             add    $0x8,%rsp12a4:       c3                      retq   

可以看到,這個程序雖然只是輸出 hello,world.,但依然很復雜,因為它要包含其它很多的基礎資源或者子程序,我們只需要重點關注 main

0000000000001189 <main>:1189:       f3 0f 1e fa             endbr64 118d:       55                      push   %rbp118e:       48 89 e5                mov    %rsp,%rbp1191:       48 8d 35 6d 0e 00 00    lea    0xe6d(%rip),%rsi        # 2005 <_ZStL19piecewise_construct+0x1>1198:       48 8d 3d 81 2e 00 00    lea    0x2e81(%rip),%rdi        # 4020 <_ZSt4cerr@@GLIBCXX_3.4>119f:       e8 dc fe ff ff          callq  1080 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>11a4:       b8 00 00 00 00          mov    $0x0,%eax11a9:       5d                      pop    %rbp11aa:       c3                      retq   

可以看到,這個段是從0000000000001189開始的,需要關注的輸出語句為:

    119f:       e8 dc fe ff ff          callq  1080 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>

這個地址 119f 就是我們需要打斷點的地方,被我們找出來了,這個地址是定死的,它在運行的時候,需要加載到內存中。問題是,加載到哪里?

我們并不知道加載到哪里,換句話說,我們不知道段地址是什么,它不固定,這主要是為了程序數據安全考慮,采用了內存分布隨機化,我們可以關掉內存分布隨機化

if (pid == 0) {personality(ADDR_NO_RANDOMIZE); // 取消隨機內存// child progress// debugged progressptrace(PTRACE_TRACEME, 0, nullptr, nullptr);execl(proj, proj, nullptr);...

這樣它就固定了,我們可以這樣查看它在運行的時候的 map,首先用我們程序進行調試:

./main hw
Start debugging the progress: hw, pid = 260915:
minidbg> 

可以看到,pid260915,另開一個 zsh,直接查看:

cat /proc/260915/maps
555555554000-555555555000 r--p 00000000 fc:01 698165                     /root/mydebugger/src/hw
555555555000-555555556000 r-xp 00001000 fc:01 698165                     /root/mydebugger/src/hw
555555556000-555555557000 r--p 00002000 fc:01 698165                     /root/mydebugger/src/hw
555555557000-555555559000 rw-p 00002000 fc:01 698165                     /root/mydebugger/src/hw
7ffff7fcb000-7ffff7fce000 r--p 00000000 00:00 0                          [vvar]
7ffff7fce000-7ffff7fcf000 r-xp 00000000 00:00 0                          [vdso]
7ffff7fcf000-7ffff7fd0000 r--p 00000000 fc:01 1185709                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7ffff7fd0000-7ffff7ff3000 r-xp 00001000 fc:01 1185709                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7ffff7ff3000-7ffff7ffb000 r--p 00024000 fc:01 1185709                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7ffff7ffc000-7ffff7ffe000 rw-p 0002c000 fc:01 1185709                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0 
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0

可以看到我們的可執行代碼也就是 main 段在這里:

555555555000-555555556000 r-xp 00001000 fc:01 698165                     /root/mydebugger/src/hw

這以后都是固定的,雖然不安全,但是僅僅是為了演示,就沒關系了。段的偏移地址為555555554000,因為我們需要打斷點的地址為119f,因此:

基址 + 指令相對地址
= 555555554000 + 119f
= 55555555519f

可以預見的是,如果 break 0x55555555519f,之后執行,并不會打印出 hello,world,但是我們如果打到了下一條地址:0x5555555551a4,運行之后,就會理解打印出 hello,world。以下進行檢測:

./main hw
Start debugging the progress: hw, pid = 261169:
minidbg> break 0x55555555519f
Set breakpoint at address 0x55555555519f
minidbg> continue
minidbg> 

我們換一個地址:

./main hw
Start debugging the progress: hw, pid = 261407:
minidbg> break 0x0x5555555551a4
Set breakpoint at address 0x5555555551a4
minidbg> continue
hello,world.
minidbg> 

可以看到,以下就打印出了hello,world。以上符合我們的預期,因此實驗是成功的,另外不需要擔心 pid 不一樣,由于我們關閉了地址空間布局隨機化(ASLR, Address Space Layout Randomization),段地址不會變,因此地址也是固定的。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/15745.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/15745.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/15745.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【一站式學會Kotlin】第八節:kotlin== 和 === 的差別和含義

作者介紹&#xff1a; 百度資深Android工程師T6&#xff0c;在百度任職7年半。 目前&#xff1a;成立趙小灰代碼工作室&#xff0c;歡迎大家找我交流Android、微信小程序、鴻蒙項目。 一&#xff1a;通俗易懂的人工智能教程&#xff1a;https://www.captainbed.cn/nefu/ 點一下…

Altium Designer 中鍵拖動,滾輪縮放,并修改縮放速度

我的版本是AD19&#xff0c;其他版本應該都一樣。 滾輪縮放 首先&#xff0c;要用滾輪縮放&#xff0c;先要調整一下AD 設置&#xff0c;打開Preferences&#xff0c;在Mouse Wheel Configuration 里&#xff0c;把Zoom Main Window 后面Ctrl 上的對勾取消掉&#xff0c;再把…

C++中的懸掛指針和野指針

懸掛指針&#xff08;dangling pointer&#xff09;和野指針&#xff08;wild pointer&#xff09;是兩種常見的指針錯誤&#xff0c;雖然它們都可能導致未定義行為&#xff0c;但它們產生的原因和表現有所不同。 1.懸掛指針&#xff08;Dangling Pointer&#xff09; 懸掛指…

2024 ISCC pwn wp

iscc 練武pwn 總結第一周chaosISCC_easyFlagshopping 第二周ISCC_easyISCC_Uheapheap 第三周miaoYour_programeazy_heap 總結 總體感覺iscc考察的題目都挺基礎的&#xff0c;在目前這種比賽的大環境下&#xff0c;仍然出這種&#xff0c;比較基礎的題目&#xff0c;實在是難得…

智馭未來:探究AIGC行業的戰略入局時機與前景展望

當前時點涉足人工智能生成內容&#xff08;AIGC&#xff09;行業&#xff0c;是一個策略性抉擇&#xff0c;基于對該行業現狀的深度剖析及對未來趨勢的前瞻性預判&#xff0c;其可行性與吸引力顯著。 行業發展階段分析&#xff1a; 技術迭代加速&#xff1a;近年來&#xff0c…

力扣刷題---2283. 判斷一個數的數字計數是否等于數位的值【簡單】

題目描述 給你一個下標從 0 開始長度為 n 的字符串 num &#xff0c;它只包含數字。 如果對于 每個 0 < i < n 的下標 i &#xff0c;都滿足數位 i 在 num 中出現了 num[i]次&#xff0c;那么請你返回 true &#xff0c;否則返回 false 。 示例 1&#xff1a; 輸入&a…

SpringCloud系列(31)--使用Hystrix進行服務降級

前言&#xff1a;在上一章節中我們創建了服務消費者模塊&#xff0c;而本節內容則是使用Hystrix對服務進行服務降級處理。 1、首先我們先對服務提供者的服務進行服務降級處理 (1)修改cloud-provider-hystrix-payment8001子模塊的PaymentServiceImpl類 注&#xff1a;HystrixP…

學習elixir(1)

突然發現elixir很有趣&#xff0c;所以想記錄以下學習內容 # .ex .exs file elixir simple.exs # mix new <app_name> # mix deps.get; mix deps.update; mix deps.compile # 怎么使用mix escript.build # eg. 在mix.exs添加escript: [main_module: IntentionCLI, name:…

Window在VScode運行C/C++程序

首先說明&#xff1a;不同運行環境&#xff08;Linux/Window&#xff09;下的頭文件會有差異&#xff0c;要注意變換&#xff01;生成可執行文件 Window默認生成a.exe&#xff0c;Linux默認生成a.out # C源代碼 g test.cpp # C語言源代碼 g test.c 或 gcc test.c直接輸入a.ex…

從零開始學逆向,js逆向啟蒙:有道翻譯

語言&#xff1a;js、python 工具&#xff1a;pycharm、chrome瀏覽器F12調試、chatgpt&#xff08;補充js第三方庫&#xff0c;轉python&#xff09;、node.js(js運行)&#xff08;必須&#xff09; 目標&#xff1a;學習掌握基本js逆向知識。 對象&#xff1a; 有道翻譯 &a…

怎么判斷同步時序邏輯電路和異步時序邏輯電路?

&#x1f3c6;本文收錄于「Bug調優」專欄&#xff0c;主要記錄項目實戰過程中的Bug之前因后果及提供真實有效的解決方案&#xff0c;希望能夠助你一臂之力&#xff0c;幫你早日登頂實現財富自由&#x1f680;&#xff1b;同時&#xff0c;歡迎大家關注&&收藏&&…

力扣刷題---2418. 按身高排序【簡單】

題目描述 給你一個字符串 數組 names &#xff0c;和一個由 互不相同 的正整數組成的數組 heights 。兩個數組的長度均為 n 。 對于每個下標 i&#xff0c;names[i] 和 heights[i] 表示第 i 個人的名字和身高。 請按身高 降序 順序返回對應的名字數組 names 。 示例 1&…

僵尸進程,孤兒進程,守護進程

【一】僵尸進程 1.僵尸進程是指完成自己的任務之后&#xff0c;沒有被父進程回收資源,占用系統資源,對計算機有害&#xff0c;應該避免 """ 所有的子進程在運行結束之后都會變成僵尸進程(死了沒死透)還保留著pid和一些運行過程的中的記錄便于主進程查看(短時間…

嵌入式作業5

在函數main.c中初始化三種顏色的燈&#xff1a; gpio_init(LIGHT_BLUE, GPIO_OUTPUT, LIGHT_OFF); //藍燈 gpio_init(LIGHT_GREEN, GPIO_OUTPUT, LIGHT_OFF); //綠燈 gpio_init(LIGHT_RED, GPIO_OUTPUT, LIGHT_OFF); //紅燈 同時為了響應以上修改&#xff0c;進入isr。c…

STM32 CubeMX使用記錄

取消DMA中斷默認使能 DMA中斷默認使能勾選無法取消選中 取消勾選Force DMA channels interrupts

cadence23---PCB Editer 學習筆記

1.交互式布局 在Orcad中點擊圖標N生成第一網表&#xff1a; 在PCB Editer中導入第一網表&#xff0c; 之后點擊移動命令并在右側屬性框中勾選Symbol選項卡&#xff1a; 設置--應用模式--點擊常規編輯&#xff1a; 之后就可以進行交互式選擇了。 綠色圖標為打開全部飛線&#…

web前端學習筆記11

11. CSS3高級特效 11.1 CSS3變形 CSS3變形是一些效果的集合, 如平移、旋轉、縮放、傾斜效果 每個效果都可以稱為變形(transform),它們可以分別操控元素發生平移、旋轉、縮放、傾斜等變化 語法 transform:[transform-function] ; /* 設置變形函數,可以是一個,也可以是多…

2024年【N1叉車司機】考試題及N1叉車司機找解析

題庫來源&#xff1a;安全生產模擬考試一點通公眾號小程序 N1叉車司機考試題參考答案及N1叉車司機考試試題解析是安全生產模擬考試一點通題庫老師及N1叉車司機操作證已考過的學員匯總&#xff0c;相對有效幫助N1叉車司機找解析學員順利通過考試。 1、【多選題】《特種設備使用…

git使用介紹

一、為什么做版本控制&#xff08;git是版本控制工具&#xff09; 為了保留之前所以的版本&#xff0c;以便回滾和修改 二、點擊安裝 三、基礎操作 1、初步認識 想要讓git對一個目錄進行版本控制需要以下步驟&#xff1a; 進入要管理的文件夾進行初始化命令 git init管理…

Amesim基礎篇-元件詳解-H型膨脹閥四象限解析

一 膨脹閥簡介 膨脹閥的主要功能是節流和調節過熱度,庫內膨脹閥包含節流管、H型膨脹閥、T型膨脹閥三種: 節流管:一根內徑較小的管路,當制冷劑通過他時發生等等焓降壓降溫,具有成本低,內徑不可變的特點,因此普遍在家用空調中使用,在汽車空調上使用較少。當我們建模過程…