├── .vscode └── tasks.json ├── 01保护模式.md ├── 01保护模式 ├── image-20220409162131390.png ├── image-20220409162959029.png ├── image-20220409170300022.png ├── image-20220409170426468.png ├── image-20220409171001033.png ├── image-20220409171549067.png ├── image-20220705133725810.png ├── image-20220705143157265.png ├── image-20220705202235583.png ├── image-20220705203046305.png ├── image-20220705203118342.png ├── image-20220705203213609.png ├── image-20220705204015260.png ├── image-20220705204208426.png ├── image-20220705204224645.png ├── image-20220705205330142.png ├── image-20220705205642078.png ├── image-20220705205746223.png ├── image-20220705205821563.png ├── image-20220915154318677.png ├── image-20220915154357463.png ├── image-20220915155154854.png ├── image-20220915160041371.png ├── image-20220915163111192.png ├── image-20220915163545870.png ├── image-20220915163613567.png ├── image-20220915164138159.png ├── image-20220915164331943.png ├── image-20220915170010817.png ├── image-20220915170021012.png ├── image-20220916164814247.png ├── image-20220916232442504.png ├── image-20220916233410021.png ├── image-20220916233912720.png ├── image-20220916233949926.png ├── image-20220916234159283.png ├── image-20220916235233228.png ├── image-20220917094545158.png ├── image-20220917100007067.png ├── image-20220917100052830.png ├── image-20220917100944324.png ├── image-20220917101400290.png ├── image-20220917103115783.png ├── image-20220917103501066.png ├── image-20220917104302437.png ├── image-20220917172922264.png ├── image-20220917173106598.png ├── image-20220917173121555.png ├── image-20220917214430495.png ├── image-20220917214509330.png ├── image-20220917215214051.png ├── image-20220917221940639.png ├── image-20220918144624863.png ├── image-20220918145721145.png ├── image-20220918150026313.png ├── image-20220918150143370.png ├── image-20220918150308389.png ├── image-20220918151003514.png ├── image-20220918152409888.png ├── image-20220918152641394.png ├── image-20220918152850045.png ├── image-20220918153023964.png ├── image-20220918153103508.png ├── image-20220918153555496.png ├── image-20220918214341108.png ├── image-20220918214451606.png ├── image-20220918220442272.png ├── image-20220918220530341.png ├── image-20220919215916582.png ├── image-20220920000300402.png ├── image-20220920000407513.png ├── image-20220920000444805.png ├── image-20220920000540021.png ├── image-20220924211956538.png ├── image-20220925121337378.png ├── image-20220925121843125.png ├── image-20220925122123519.png ├── image-20220925122137925.png ├── image-20220925122155565.png ├── image-20220925123759825.png ├── image-20220925124839590.png ├── image-20220926204910845.png ├── image-20220926205843621.png ├── image-20220926211210422.png ├── image-20220926212001922.png ├── image-20220926213928875.png ├── image-20220926214258402.png ├── image-20220926221614422.png ├── image-20220926221649224.png ├── image-20220926221836085.png └── image-20220926221851332.png ├── 02驱动.md ├── 02驱动 ├── image-20221213184310074.png ├── image-20221213184334246.png ├── image-20230104160816744.png ├── image-20230104201904553.png ├── image-20230104204933253.png ├── image-20230105122422110.png ├── image-20230105123953034.png ├── image-20230105133925444.png ├── image-20230105134550612.png ├── image-20230105134937086.png ├── image-20230105135002493.png ├── image-20230105135139857.png ├── image-20230105141141521.png ├── image-20230105143451165.png ├── image-20230105213719638.png ├── image-20230107230553238.png ├── image-20230117144628641.png ├── image-20230117144735160.png ├── image-20230117145313399.png ├── image-20230117145749081.png ├── image-20230117150934452.png ├── image-20230117151029551.png ├── image-20230117151105934.png ├── image-20230117201023604.png ├── image-20230117235309994.png ├── image-20230117235442739.png ├── image-20230117235457065.png └── image-20230117235958593.png ├── 03系统调用.md ├── 03系统调用 ├── image-20230106134533807.png ├── image-20230106134646722.png ├── image-20230106140227852.png ├── image-20230106140509018.png ├── image-20230106141108580.png ├── image-20230106142000444.png ├── image-20230106142020461.png ├── image-20230106143004394.png ├── image-20230107134858939.png ├── image-20230107230553238.png ├── image-20230107230710291.png ├── image-20230107234334197.png ├── image-20230107235014722.png └── image-20230107235309282.png ├── 04进程与线程.md ├── 04进程与线程 ├── image-20230119203755480.png ├── image-20230218163344642.png ├── image-20230218165731076.png ├── image-20230218165835614.png ├── image-20230218174027106.png ├── image-20230218205639146.png ├── image-20230219125142968.png └── watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0t3YW5zeQ==,size_16,color_FFFFFF,t_70#pic_center.png ├── 05句柄表.md ├── 05句柄表 ├── 2520882-20220119172827300-822756739.png ├── image-20230219172158354.png ├── image-20230219180656748.png ├── image-20230219181053778.png ├── image-20230219184646960.png └── image-20230219190424244.png ├── 06事件等待.md ├── 06事件等待 ├── 2520882-20220211162824199-327227111.png ├── 2520882-20220211162831246-1280864920.png ├── 2520882-20220211162838959-1627623022.png ├── 2520882-20220211175941247-1806950584.png ├── image-20230220171234183.png ├── image-20230221104041091.png ├── image-20230221104359682.png ├── image-20230221104635043.png └── image-20230221111107246.png ├── 07APC机制.md ├── 07APC机制 ├── 1827556-20191103170141163-71115727.png └── image-20230224142512175.png ├── 08异常.md ├── 08异常 ├── 835440_CA2S8CBBYXKKJ7B.png ├── image-20230224184604177.png ├── image-20230225143409781.png ├── image-20230225143525207.png ├── image-20230225144037458.png ├── image-20230225144809214.png ├── image-20230225153154252.png ├── image-20230225175242015.png ├── image-20230225175253317.png ├── image-20230225182333244.png ├── image-20230225182342263.png ├── image-20230225191306047.png ├── image-20230225191407445.png └── image-20230225192811099.png ├── 09内存管理.md ├── 09内存管理 ├── image-20230226183309832.png ├── image-20230227102011045.png ├── image-20230227102049345.png ├── image-20230227110744432.png ├── image-20230227111808658.png ├── image-20230304142407074.png └── image-20230304144643458.png ├── 10消息机制.md ├── 10消息机制 ├── image-20230304145550736.png ├── image-20230308204349224.png ├── image-20230308211449772.png ├── image-20230308211547780.png └── image-20230308211627411.png ├── 11.软件调试.md ├── 11.软件调试 ├── image-20230308214733381.png ├── image-20230309191507860.png ├── image-20230310163025978.png ├── image-20230310163210216.png ├── image-20230310163423081.png ├── image-20230311110109036.png ├── image-20230311110308508.png ├── image-20230311111044990.png ├── image-20230311111147695.png ├── image-20230311111507666.png ├── image-20230311111947844.png ├── image-20230311112041778.png ├── image-20230311121728853.png ├── image-20230311230028195.png ├── image-20230312115603417.png └── image-20230312120730668.png └── README.md /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": [ 3 | { 4 | "type": "cppbuild", 5 | "label": "C/C++: g++.exe 生成活动文件", 6 | "command": "C:\\MinGW-x64\\mingw64\\bin\\g++.exe", 7 | "args": [ 8 | "-fdiagnostics-color=always", 9 | "-g", 10 | "${file}", 11 | "-o", 12 | "${fileDirname}\\${fileBasenameNoExtension}.exe" 13 | ], 14 | "options": { 15 | "cwd": "${fileDirname}" 16 | }, 17 | "problemMatcher": [ 18 | "$gcc" 19 | ], 20 | "group": { 21 | "kind": "build", 22 | "isDefault": true 23 | }, 24 | "detail": "调试器生成的任务。" 25 | } 26 | ], 27 | "version": "2.0.0" 28 | } -------------------------------------------------------------------------------- /01保护模式/image-20220409162131390.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220409162131390.png -------------------------------------------------------------------------------- /01保护模式/image-20220409162959029.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220409162959029.png -------------------------------------------------------------------------------- /01保护模式/image-20220409170300022.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220409170300022.png -------------------------------------------------------------------------------- /01保护模式/image-20220409170426468.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220409170426468.png -------------------------------------------------------------------------------- /01保护模式/image-20220409171001033.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220409171001033.png -------------------------------------------------------------------------------- /01保护模式/image-20220409171549067.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220409171549067.png -------------------------------------------------------------------------------- /01保护模式/image-20220705133725810.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220705133725810.png -------------------------------------------------------------------------------- /01保护模式/image-20220705143157265.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220705143157265.png -------------------------------------------------------------------------------- /01保护模式/image-20220705202235583.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220705202235583.png -------------------------------------------------------------------------------- /01保护模式/image-20220705203046305.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220705203046305.png -------------------------------------------------------------------------------- /01保护模式/image-20220705203118342.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220705203118342.png -------------------------------------------------------------------------------- /01保护模式/image-20220705203213609.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220705203213609.png -------------------------------------------------------------------------------- /01保护模式/image-20220705204015260.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220705204015260.png -------------------------------------------------------------------------------- /01保护模式/image-20220705204208426.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220705204208426.png -------------------------------------------------------------------------------- /01保护模式/image-20220705204224645.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220705204224645.png -------------------------------------------------------------------------------- /01保护模式/image-20220705205330142.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220705205330142.png -------------------------------------------------------------------------------- /01保护模式/image-20220705205642078.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220705205642078.png -------------------------------------------------------------------------------- /01保护模式/image-20220705205746223.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220705205746223.png -------------------------------------------------------------------------------- /01保护模式/image-20220705205821563.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220705205821563.png -------------------------------------------------------------------------------- /01保护模式/image-20220915154318677.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220915154318677.png -------------------------------------------------------------------------------- /01保护模式/image-20220915154357463.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220915154357463.png -------------------------------------------------------------------------------- /01保护模式/image-20220915155154854.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220915155154854.png -------------------------------------------------------------------------------- /01保护模式/image-20220915160041371.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220915160041371.png -------------------------------------------------------------------------------- /01保护模式/image-20220915163111192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220915163111192.png -------------------------------------------------------------------------------- /01保护模式/image-20220915163545870.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220915163545870.png -------------------------------------------------------------------------------- /01保护模式/image-20220915163613567.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220915163613567.png -------------------------------------------------------------------------------- /01保护模式/image-20220915164138159.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220915164138159.png -------------------------------------------------------------------------------- /01保护模式/image-20220915164331943.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220915164331943.png -------------------------------------------------------------------------------- /01保护模式/image-20220915170010817.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220915170010817.png -------------------------------------------------------------------------------- /01保护模式/image-20220915170021012.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220915170021012.png -------------------------------------------------------------------------------- /01保护模式/image-20220916164814247.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220916164814247.png -------------------------------------------------------------------------------- /01保护模式/image-20220916232442504.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220916232442504.png -------------------------------------------------------------------------------- /01保护模式/image-20220916233410021.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220916233410021.png -------------------------------------------------------------------------------- /01保护模式/image-20220916233912720.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220916233912720.png -------------------------------------------------------------------------------- /01保护模式/image-20220916233949926.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220916233949926.png -------------------------------------------------------------------------------- /01保护模式/image-20220916234159283.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220916234159283.png -------------------------------------------------------------------------------- /01保护模式/image-20220916235233228.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220916235233228.png -------------------------------------------------------------------------------- /01保护模式/image-20220917094545158.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220917094545158.png -------------------------------------------------------------------------------- /01保护模式/image-20220917100007067.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220917100007067.png -------------------------------------------------------------------------------- /01保护模式/image-20220917100052830.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220917100052830.png -------------------------------------------------------------------------------- /01保护模式/image-20220917100944324.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220917100944324.png -------------------------------------------------------------------------------- /01保护模式/image-20220917101400290.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220917101400290.png -------------------------------------------------------------------------------- /01保护模式/image-20220917103115783.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220917103115783.png -------------------------------------------------------------------------------- /01保护模式/image-20220917103501066.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220917103501066.png -------------------------------------------------------------------------------- /01保护模式/image-20220917104302437.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220917104302437.png -------------------------------------------------------------------------------- /01保护模式/image-20220917172922264.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220917172922264.png -------------------------------------------------------------------------------- /01保护模式/image-20220917173106598.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220917173106598.png -------------------------------------------------------------------------------- /01保护模式/image-20220917173121555.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220917173121555.png -------------------------------------------------------------------------------- /01保护模式/image-20220917214430495.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220917214430495.png -------------------------------------------------------------------------------- /01保护模式/image-20220917214509330.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220917214509330.png -------------------------------------------------------------------------------- /01保护模式/image-20220917215214051.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220917215214051.png -------------------------------------------------------------------------------- /01保护模式/image-20220917221940639.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220917221940639.png -------------------------------------------------------------------------------- /01保护模式/image-20220918144624863.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220918144624863.png -------------------------------------------------------------------------------- /01保护模式/image-20220918145721145.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220918145721145.png -------------------------------------------------------------------------------- /01保护模式/image-20220918150026313.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220918150026313.png -------------------------------------------------------------------------------- /01保护模式/image-20220918150143370.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220918150143370.png -------------------------------------------------------------------------------- /01保护模式/image-20220918150308389.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220918150308389.png -------------------------------------------------------------------------------- /01保护模式/image-20220918151003514.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220918151003514.png -------------------------------------------------------------------------------- /01保护模式/image-20220918152409888.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220918152409888.png -------------------------------------------------------------------------------- /01保护模式/image-20220918152641394.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220918152641394.png -------------------------------------------------------------------------------- /01保护模式/image-20220918152850045.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220918152850045.png -------------------------------------------------------------------------------- /01保护模式/image-20220918153023964.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220918153023964.png -------------------------------------------------------------------------------- /01保护模式/image-20220918153103508.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220918153103508.png -------------------------------------------------------------------------------- /01保护模式/image-20220918153555496.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220918153555496.png -------------------------------------------------------------------------------- /01保护模式/image-20220918214341108.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220918214341108.png -------------------------------------------------------------------------------- /01保护模式/image-20220918214451606.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220918214451606.png -------------------------------------------------------------------------------- /01保护模式/image-20220918220442272.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220918220442272.png -------------------------------------------------------------------------------- /01保护模式/image-20220918220530341.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220918220530341.png -------------------------------------------------------------------------------- /01保护模式/image-20220919215916582.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220919215916582.png -------------------------------------------------------------------------------- /01保护模式/image-20220920000300402.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220920000300402.png -------------------------------------------------------------------------------- /01保护模式/image-20220920000407513.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220920000407513.png -------------------------------------------------------------------------------- /01保护模式/image-20220920000444805.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220920000444805.png -------------------------------------------------------------------------------- /01保护模式/image-20220920000540021.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220920000540021.png -------------------------------------------------------------------------------- /01保护模式/image-20220924211956538.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220924211956538.png -------------------------------------------------------------------------------- /01保护模式/image-20220925121337378.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220925121337378.png -------------------------------------------------------------------------------- /01保护模式/image-20220925121843125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220925121843125.png -------------------------------------------------------------------------------- /01保护模式/image-20220925122123519.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220925122123519.png -------------------------------------------------------------------------------- /01保护模式/image-20220925122137925.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220925122137925.png -------------------------------------------------------------------------------- /01保护模式/image-20220925122155565.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220925122155565.png -------------------------------------------------------------------------------- /01保护模式/image-20220925123759825.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220925123759825.png -------------------------------------------------------------------------------- /01保护模式/image-20220925124839590.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220925124839590.png -------------------------------------------------------------------------------- /01保护模式/image-20220926204910845.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220926204910845.png -------------------------------------------------------------------------------- /01保护模式/image-20220926205843621.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220926205843621.png -------------------------------------------------------------------------------- /01保护模式/image-20220926211210422.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220926211210422.png -------------------------------------------------------------------------------- /01保护模式/image-20220926212001922.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220926212001922.png -------------------------------------------------------------------------------- /01保护模式/image-20220926213928875.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220926213928875.png -------------------------------------------------------------------------------- /01保护模式/image-20220926214258402.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220926214258402.png -------------------------------------------------------------------------------- /01保护模式/image-20220926221614422.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220926221614422.png -------------------------------------------------------------------------------- /01保护模式/image-20220926221649224.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220926221649224.png -------------------------------------------------------------------------------- /01保护模式/image-20220926221836085.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220926221836085.png -------------------------------------------------------------------------------- /01保护模式/image-20220926221851332.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/01保护模式/image-20220926221851332.png -------------------------------------------------------------------------------- /02驱动/image-20221213184310074.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20221213184310074.png -------------------------------------------------------------------------------- /02驱动/image-20221213184334246.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20221213184334246.png -------------------------------------------------------------------------------- /02驱动/image-20230104160816744.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230104160816744.png -------------------------------------------------------------------------------- /02驱动/image-20230104201904553.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230104201904553.png -------------------------------------------------------------------------------- /02驱动/image-20230104204933253.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230104204933253.png -------------------------------------------------------------------------------- /02驱动/image-20230105122422110.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230105122422110.png -------------------------------------------------------------------------------- /02驱动/image-20230105123953034.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230105123953034.png -------------------------------------------------------------------------------- /02驱动/image-20230105133925444.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230105133925444.png -------------------------------------------------------------------------------- /02驱动/image-20230105134550612.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230105134550612.png -------------------------------------------------------------------------------- /02驱动/image-20230105134937086.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230105134937086.png -------------------------------------------------------------------------------- /02驱动/image-20230105135002493.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230105135002493.png -------------------------------------------------------------------------------- /02驱动/image-20230105135139857.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230105135139857.png -------------------------------------------------------------------------------- /02驱动/image-20230105141141521.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230105141141521.png -------------------------------------------------------------------------------- /02驱动/image-20230105143451165.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230105143451165.png -------------------------------------------------------------------------------- /02驱动/image-20230105213719638.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230105213719638.png -------------------------------------------------------------------------------- /02驱动/image-20230107230553238.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230107230553238.png -------------------------------------------------------------------------------- /02驱动/image-20230117144628641.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230117144628641.png -------------------------------------------------------------------------------- /02驱动/image-20230117144735160.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230117144735160.png -------------------------------------------------------------------------------- /02驱动/image-20230117145313399.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230117145313399.png -------------------------------------------------------------------------------- /02驱动/image-20230117145749081.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230117145749081.png -------------------------------------------------------------------------------- /02驱动/image-20230117150934452.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230117150934452.png -------------------------------------------------------------------------------- /02驱动/image-20230117151029551.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230117151029551.png -------------------------------------------------------------------------------- /02驱动/image-20230117151105934.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230117151105934.png -------------------------------------------------------------------------------- /02驱动/image-20230117201023604.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230117201023604.png -------------------------------------------------------------------------------- /02驱动/image-20230117235309994.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230117235309994.png -------------------------------------------------------------------------------- /02驱动/image-20230117235442739.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230117235442739.png -------------------------------------------------------------------------------- /02驱动/image-20230117235457065.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230117235457065.png -------------------------------------------------------------------------------- /02驱动/image-20230117235958593.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/02驱动/image-20230117235958593.png -------------------------------------------------------------------------------- /03系统调用.md: -------------------------------------------------------------------------------- 1 | [toc] 2 | 3 | 4 | 5 | # 001.API函数的调用过程(3环部分) 6 | 7 | 主要是存放在 C:\WINDOWS\system32 下面所有的dll 8 | 9 | 几个重要的DLL 10 | 11 | - Kernel32.dll:最核心的功能模块,比如管理内存、进程和线程相关的函数等. 12 | - User32.dll:是Windows用户界面相关应用程序接口,如创建窗口和发送消息等. 13 | - GDI32.dll:全称是Graphical Device Interface(图形设备接口),包含用于画图和显示文本的函数.比如要显示一个程序窗口,就调用了其中的函数来画这个窗口. 14 | - Ntdll.dll:大多数API都会通过这个DLL进入内核(0环). 15 | 16 | alt+t直接搜就行,这里使用`ReadProcesMemory`来举例 17 | 18 | 首先是kernel32这个dll 19 | 20 | 可以看到是call了一个函数,之后巴拉巴拉, 21 | 22 | ![image-20230106134646722](./03系统调用/image-20230106134646722.png) 23 | 24 | 调用的这个函数在ntdll这个dll里面,在import可以看到,他做了这些事:其中的`0BA`是一个编号,`7FFE0300`决定以什么方式进0环 25 | 26 | ![image-20230106134533807](./03系统调用/image-20230106134533807.png) 27 | 28 | > kernel32.dll(ReadProcessMemory) => 29 | > 30 | > ntdll.dll(NtReadVirtualMemory) 31 | 32 | # 002.API函数的调用过程(3环进0环 上) 33 | 34 | 下面说下这部分: 35 | 36 | ![image-20230106134533807](./03系统调用/image-20230106134533807.png) 37 | 38 | 首先是`7FFE0300`这个地址 39 | 40 | ## _KUSER_SHARED_DATA 41 | 42 | 1. 在 User 层和 Kernel 层分别定义了一个 `_KUSER_SHARED_DATA` 结构区域,用于 User 层和 Kernel 层共享某些数据 43 | 2. 它们使用固定的地址值映射,`_KUSER_SHARED_DATA` 结构区域在 User 和 Kernel 层地址分别为: 44 | - User 层地址为:0x7ffe0000 45 | - Kernnel 层地址为:0xffdf0000 46 | 47 | 特别说明: 48 | 49 | 虽然指向的是同一个物理页,但在User 层是只读的,在Kernnel层是可写的. 50 | 51 | 可以看到两者都是一样的: 52 | 53 | ![image-20230106140227852](./03系统调用/image-20230106140227852.png) 54 | 55 | 可以看到300的位置是系统调用: 56 | 57 | ![image-20230106140509018](./03系统调用/image-20230106140509018.png) 58 | 59 | ## CPU是否支持快速调用 60 | 61 | 实验:是否支持快速调用 62 | 63 | 当通过`eax=1`来执行`cpuid`指令时,处理器的特征信息被放在`ecx`和`edx`寄存器中,其中`edx`包含了一个`SEP`位(11位),该位指明了当前处理器知否支持`sysenter/sysexit`指令 64 | 65 | - 支持:ntdll.dll!KiFastSystemCall() 66 | - 不支持:ntdll.dll!KiIntSystemCall() 67 | 68 | eax置1后执行,发现是0xBFF,第11位是1,表示支持 69 | 70 | ![image-20230106141108580](./03系统调用/image-20230106141108580.png) 71 | 72 | 当系统启动的时候,上述执行,之后将相应的函数放到偏移0x300的位置。 73 | 74 | ## 进R0需要更改哪些寄存器 75 | 76 | 1) CS的权限由3变为0,意味着需要新的CS 77 | 78 | 2) SS与CS的权限永远一致,需要新的SS 79 | 80 | 3) 权限发生切换的时候,堆栈也一定会切换,需要新的ESP 81 | 82 | 4) 进0环后代码的位置,需要EIP 83 | 84 | -------- 85 | 86 | 不支持的时候使用的是`ntdll.dll!KiIntSystemCall()` 87 | 88 | 将eax中的编号和edx(参数指针),之后中断`0x2E`进入内核 89 | 90 | ![image-20230106142000444](./03系统调用/image-20230106142000444.png) 91 | 92 | ```sh 93 | kd> dq 8003f400+170 94 | ReadVirtual: 8003f570 not properly sign extended 95 | 8003f570 8054ee00`00082611 80548e00`0008590c 96 | 8003f580 80548e00`00081cd0 80548e00`00081cda 97 | 8003f590 80548e00`00081ce4 80548e00`00081cee 98 | 8003f5a0 80548e00`00081cf8 80548e00`00081d02 99 | 8003f5b0 80548e00`00081d0c 806e8e00`00087864 100 | 8003f5c0 80548e00`00081d20 80548e00`00081d2a 101 | 8003f5d0 80548e00`00081d34 80548e00`00081d3e 102 | 8003f5e0 80548e00`00081d48 806e8e00`00088e2c 103 | kd> u 80542611 104 | ReadVirtual: 80542611 not properly sign extended 105 | 80542611 6a00 push 0 106 | 80542613 55 push ebp 107 | 80542614 53 push ebx 108 | 80542615 56 push esi 109 | 80542616 57 push edi 110 | 80542617 0fa0 push fs 111 | 80542619 bb30000000 mov ebx,30h 112 | 8054261e 668ee3 mov fs,bx 113 | 114 | ``` 115 | 116 | 支持快速调用的时候使用`ntdll.dll!KiFastSystemCall()` 117 | 118 | 也就2行代码: 119 | 120 | 121 | 122 | ![image-20230106143004394](./03系统调用/image-20230106143004394.png) 123 | 124 | 125 | 126 | 中断门进0环,需要的CS、EIP在IDT表中,需要查内存(SS与ESP由TSS提供)而CPU如果支持sysenter指令时,操作系统会提前将CS/SS/ESP/EIP的值存储在MSR寄存器中,sysenter指令执行时,CPU会将MSR寄存器中的值直接写入相关寄存器,没有读内存的过程,所以叫快速调用,本质是一样的! 127 | 128 | 129 | 130 | # 003.API函数的调用过程(3环进0环 下) 131 | 132 | 不支持快速调用的话就中断进0环,支持的话就sysenter,需要的寄存器信息(CS,SS,ESP,EIP)在`MSR`寄存器中可以找到:(ss在cs+8的位置) 133 | 134 | | **MSR** | **地址** | 135 | | ----------------- | -------- | 136 | | IA32_SYSENTER_CS | 174H | 137 | | IA32_SYSENTER_ESP | 175H | 138 | | IA32_SYSENTER_EIP | 176H | 139 | 140 | 可以通过RDMSR/WRMST来进行读写(操作系统使用WRMST写该寄存器): 141 | 142 | ```sh 143 | kd> rdmsr 174 //查看CS 144 | kd> rdmsr 175 //查看ESP 145 | kd> rdmsr 176 //查看EIP 146 | > 参考:Intel白皮书第二卷(搜索sysenter) 147 | ``` 148 | 149 | ``` 150 | kd> rdmsr 174 151 | msr[174] = 00000000`00000008 152 | kd> rdmsr 175 153 | msr[175] = 00000000`f78af000 154 | kd> rdmsr 176 155 | msr[176] = 00000000`805426e0 156 | kd> u 805426e0 157 | ReadVirtual: 805426e0 not properly sign extended 158 | 805426e0 b923000000 mov ecx,23h 159 | 805426e5 6a30 push 30h 160 | 805426e7 0fa1 pop fs 161 | 805426e9 8ed9 mov ds,cx 162 | 805426eb 8ec1 mov es,cx 163 | 805426ed 648b0d40000000 mov ecx,dword ptr fs:[40h] 164 | 805426f4 8b6104 mov esp,dword ptr [ecx+4] 165 | 805426f7 6a23 push 23h 166 | ``` 167 | 168 | ## 总结 169 | 170 | API通过中断门进0环: 171 | 172 | 1) 固定中断号为0x2E 173 | 2) CS/EIP由门描述符提供 ESP/SS由TSS提供 174 | 3) 进入0环后执行的内核函数:NT!KiSystemService 175 | 176 | API通过sysenter指令进0环: 177 | 178 | 1) CS/ESP/EIP由MSR寄存器提供(SS是算出来的) 179 | 2) 进入0环后执行的内核函数:NT!KiFastCallEntry 180 | 181 | 内核模块:`ntoskrnl.exe/ntkrnlpa.exe` 182 | 183 | 184 | 185 | # 004.API函数的调用过程(保存现场) 186 | 187 | 这里使用`KiSystemService`举例。 188 | 189 | 首先接收三个结构体: 190 | 191 | ## _Trap_Frame结构体 192 | 193 | 这个结构体在0环,由操作系统进行维护 194 | 195 | **无论是快速调用还是中断进0环都会将寄存器写到这个结构体里** 196 | 197 | ```sh 198 | kd> dt _ktrap_Frame 199 | ``` 200 | 201 | ![](./03系统调用/image-20230107134858939.png) 202 | 203 | 在中断进入0环的时候,会压入`0x068~0x078`的5个值,快速调用的 时候,这5个值是没有的。 204 | 205 | 206 | 207 | ## _ETHREAD线程相关的结构体 208 | 209 | 210 | 211 | ``` 212 | kd> dt _ETHREAD 213 | ntdll!_ETHREAD 214 | +0x000 Tcb : _KTHREAD 215 | +0x1c0 CreateTime : _LARGE_INTEGER 216 | +0x1c0 NestedFaultCount : Pos 0, 2 Bits 217 | +0x1c0 ApcNeeded : Pos 2, 1 Bit 218 | +0x1c8 ExitTime : _LARGE_INTEGER 219 | +0x1c8 LpcReplyChain : _LIST_ENTRY 220 | +0x1c8 KeyedWaitChain : _LIST_ENTRY 221 | +0x1d0 ExitStatus : Int4B 222 | +0x1d0 OfsChain : Ptr32 Void 223 | +0x1d4 PostBlockList : _LIST_ENTRY 224 | +0x1dc TerminationPort : Ptr32 _TERMINATION_PORT 225 | +0x1dc ReaperLink : Ptr32 _ETHREAD 226 | +0x1dc KeyedWaitValue : Ptr32 Void 227 | +0x1e0 ActiveTimerListLock : Uint4B 228 | +0x1e4 ActiveTimerListHead : _LIST_ENTRY 229 | +0x1ec Cid : _CLIENT_ID 230 | +0x1f4 LpcReplySemaphore : _KSEMAPHORE 231 | +0x1f4 KeyedWaitSemaphore : _KSEMAPHORE 232 | +0x208 LpcReplyMessage : Ptr32 Void 233 | +0x208 LpcWaitingOnPort : Ptr32 Void 234 | +0x20c ImpersonationInfo : Ptr32 _PS_IMPERSONATION_INFORMATION 235 | +0x210 IrpList : _LIST_ENTRY 236 | +0x218 TopLevelIrp : Uint4B 237 | +0x21c DeviceToVerify : Ptr32 _DEVICE_OBJECT 238 | +0x220 ThreadsProcess : Ptr32 _EPROCESS 239 | +0x224 StartAddress : Ptr32 Void 240 | +0x228 Win32StartAddress : Ptr32 Void 241 | +0x228 LpcReceivedMessageId : Uint4B 242 | +0x22c ThreadListEntry : _LIST_ENTRY 243 | +0x234 RundownProtect : _EX_RUNDOWN_REF 244 | +0x238 ThreadLock : _EX_PUSH_LOCK 245 | +0x23c LpcReplyMessageId : Uint4B 246 | +0x240 ReadClusterSize : Uint4B 247 | +0x244 GrantedAccess : Uint4B 248 | +0x248 CrossThreadFlags : Uint4B 249 | +0x248 Terminated : Pos 0, 1 Bit 250 | +0x248 DeadThread : Pos 1, 1 Bit 251 | +0x248 HideFromDebugger : Pos 2, 1 Bit 252 | +0x248 ActiveImpersonationInfo : Pos 3, 1 Bit 253 | +0x248 SystemThread : Pos 4, 1 Bit 254 | +0x248 HardErrorsAreDisabled : Pos 5, 1 Bit 255 | +0x248 BreakOnTermination : Pos 6, 1 Bit 256 | +0x248 SkipCreationMsg : Pos 7, 1 Bit 257 | +0x248 SkipTerminationMsg : Pos 8, 1 Bit 258 | +0x24c SameThreadPassiveFlags : Uint4B 259 | +0x24c ActiveExWorker : Pos 0, 1 Bit 260 | +0x24c ExWorkerCanWaitUser : Pos 1, 1 Bit 261 | +0x24c MemoryMaker : Pos 2, 1 Bit 262 | +0x250 SameThreadApcFlags : Uint4B 263 | +0x250 LpcReceivedMsgIdValid : Pos 0, 1 Bit 264 | +0x250 LpcExitThreadCalled : Pos 1, 1 Bit 265 | +0x250 AddressSpaceOwner : Pos 2, 1 Bit 266 | +0x254 ForwardClusterOnly : UChar 267 | +0x255 DisablePageFaultClustering : UChar 268 | ``` 269 | 270 | 里面有个`_KTHREAD` 271 | 272 | ``` 273 | kd> dt _KTHREAD 274 | ntdll!_KTHREAD 275 | +0x000 Header : _DISPATCHER_HEADER 276 | +0x010 MutantListHead : _LIST_ENTRY 277 | +0x018 InitialStack : Ptr32 Void 278 | +0x01c StackLimit : Ptr32 Void 279 | +0x020 Teb : Ptr32 Void 280 | +0x024 TlsArray : Ptr32 Void 281 | +0x028 KernelStack : Ptr32 Void 282 | +0x02c DebugActive : UChar 283 | +0x02d State : UChar 284 | +0x02e Alerted : [2] UChar 285 | +0x030 Iopl : UChar 286 | +0x031 NpxState : UChar 287 | +0x032 Saturation : Char 288 | +0x033 Priority : Char 289 | +0x034 ApcState : _KAPC_STATE 290 | +0x04c ContextSwitches : Uint4B 291 | +0x050 IdleSwapBlock : UChar 292 | +0x051 Spare0 : [3] UChar 293 | +0x054 WaitStatus : Int4B 294 | +0x058 WaitIrql : UChar 295 | +0x059 WaitMode : Char 296 | +0x05a WaitNext : UChar 297 | +0x05b WaitReason : UChar 298 | +0x05c WaitBlockList : Ptr32 _KWAIT_BLOCK 299 | +0x060 WaitListEntry : _LIST_ENTRY 300 | +0x060 SwapListEntry : _SINGLE_LIST_ENTRY 301 | +0x068 WaitTime : Uint4B 302 | +0x06c BasePriority : Char 303 | +0x06d DecrementCount : UChar 304 | +0x06e PriorityDecrement : Char 305 | +0x06f Quantum : Char 306 | +0x070 WaitBlock : [4] _KWAIT_BLOCK 307 | +0x0d0 LegoData : Ptr32 Void 308 | +0x0d4 KernelApcDisable : Uint4B 309 | +0x0d8 UserAffinity : Uint4B 310 | +0x0dc SystemAffinityActive : UChar 311 | +0x0dd PowerState : UChar 312 | +0x0de NpxIrql : UChar 313 | +0x0df InitialNode : UChar 314 | +0x0e0 ServiceTable : Ptr32 Void 315 | +0x0e4 Queue : Ptr32 _KQUEUE 316 | +0x0e8 ApcQueueLock : Uint4B 317 | +0x0f0 Timer : _KTIMER 318 | +0x118 QueueListEntry : _LIST_ENTRY 319 | +0x120 SoftAffinity : Uint4B 320 | +0x124 Affinity : Uint4B 321 | +0x128 Preempted : UChar 322 | +0x129 ProcessReadyQueue : UChar 323 | +0x12a KernelStackResident : UChar 324 | +0x12b NextProcessor : UChar 325 | +0x12c CallbackStack : Ptr32 Void 326 | +0x130 Win32Thread : Ptr32 Void 327 | +0x134 TrapFrame : Ptr32 _KTRAP_FRAME 328 | +0x138 ApcStatePointer : [2] Ptr32 _KAPC_STATE 329 | +0x140 PreviousMode : Char 330 | +0x141 EnableStackSwap : UChar 331 | +0x142 LargeStack : UChar 332 | +0x143 ResourceIndex : UChar 333 | +0x144 KernelTime : Uint4B 334 | +0x148 UserTime : Uint4B 335 | +0x14c SavedApcState : _KAPC_STATE 336 | +0x164 Alertable : UChar 337 | +0x165 ApcStateIndex : UChar 338 | +0x166 ApcQueueable : UChar 339 | +0x167 AutoAlignment : UChar 340 | +0x168 StackBase : Ptr32 Void 341 | +0x16c SuspendApc : _KAPC 342 | +0x19c SuspendSemaphore : _KSEMAPHORE 343 | +0x1b0 ThreadListEntry : _LIST_ENTRY 344 | +0x1b8 FreezeCount : Char 345 | +0x1b9 SuspendCount : Char 346 | +0x1ba IdealProcessor : UChar 347 | +0x1bb DisableBoost : UChar 348 | 349 | ``` 350 | 351 | 352 | 353 | ## _KPCR 354 | 355 | KPCR 叫CPU控制区(Processor Control Region) 356 | 357 | CPU也有自己的控制块,每一个CPU有一个,叫KPCR 358 | 359 | 360 | 361 | ``` 362 | kd> dt _KPCR 363 | nt!_KPCR 364 | +0x000 NtTib : _NT_TIB 365 | +0x01c SelfPcr : Ptr32 _KPCR 366 | +0x020 Prcb : Ptr32 _KPRCB 367 | +0x024 Irql : UChar 368 | +0x028 IRR : Uint4B 369 | +0x02c IrrActive : Uint4B 370 | +0x030 IDR : Uint4B 371 | +0x034 KdVersionBlock : Ptr32 Void 372 | +0x038 IDT : Ptr32 _KIDTENTRY 373 | +0x03c GDT : Ptr32 _KGDTENTRY 374 | +0x040 TSS : Ptr32 _KTSS 375 | +0x044 MajorVersion : Uint2B 376 | +0x046 MinorVersion : Uint2B 377 | +0x048 SetMember : Uint4B 378 | +0x04c StallScaleFactor : Uint4B 379 | +0x050 DebugActive : UChar 380 | +0x051 Number : UChar 381 | +0x052 Spare0 : UChar 382 | +0x053 SecondLevelCacheAssociativity : UChar 383 | +0x054 VdmAlert : Uint4B 384 | +0x058 KernelReserved : [14] Uint4B 385 | +0x090 SecondLevelCacheSize : Uint4B 386 | +0x094 HalReserved : [16] Uint4B 387 | +0x0d4 InterruptMode : Uint4B 388 | +0x0d8 Spare1 : UChar 389 | +0x0dc KernelReserved2 : [17] Uint4B 390 | +0x120 PrcbData : _KPRCB 391 | ``` 392 | 393 | 其中第一个是一个结构体`_NT_TIB` 394 | 395 | ``` 396 | kd> dt _NT_TIB 397 | ntdll!_NT_TIB 398 | +0x000 ExceptionList : Ptr32 _EXCEPTION_REGISTRATION_RECORD 399 | +0x004 StackBase : Ptr32 Void 400 | +0x008 StackLimit : Ptr32 Void 401 | +0x00c SubSystemTib : Ptr32 Void 402 | +0x010 FiberData : Ptr32 Void 403 | +0x010 Version : Uint4B 404 | +0x014 ArbitraryUserPointer : Ptr32 Void 405 | +0x018 Self : Ptr32 _NT_TIB//结构体指针 指向自己 406 | ``` 407 | 408 | `_KPRC`的最后一个也是一个结构体`_KPRCB`: 409 | 410 | ```sh 411 | kd> dt _KPRCB 412 | ntdll!_KPRCB 413 | +0x000 MinorVersion : Uint2B 414 | +0x002 MajorVersion : Uint2B 415 | +0x004 CurrentThread : Ptr32 _KTHREAD//当前CPU所执行线程的_ETHREAD 416 | +0x008 NextThread : Ptr32 _KTHREAD//下一个_ETHREAD 417 | +0x00c IdleThread : Ptr32 _KTHREAD//当所以线程都执行完了CPU就可以执行这个 418 | +0x010 Number : Char//CPU编号 419 | +0x011 Reserved : Char 420 | +0x012 BuildType : Uint2B 421 | +0x014 SetMember : Uint4B 422 | +0x018 CpuType : Char 423 | +0x019 CpuID : Char 424 | +0x01a CpuStep : Uint2B//CPU子版本号 425 | +0x01c ProcessorState : _KPROCESSOR_STATE//CPU状态 426 | +0x33c KernelReserved : [16] Uint4B 427 | +0x37c HalReserved : [16] Uint4B 428 | +0x3bc PrcbPad0 : [92] UChar 429 | +0x418 LockQueue : [16] _KSPIN_LOCK_QUEUE 430 | +0x498 PrcbPad1 : [8] UChar 431 | +0x4a0 NpxThread : Ptr32 _KTHREAD//Npx浮点处理器 最后一次用过浮点的线程 432 | +0x4a4 InterruptCount : Uint4B//中断计数 统计信息 没什么实际意义 自己调试用的 433 | +0x4a8 KernelTime : Uint4B//统计信息 434 | +0x4ac UserTime : Uint4B//统计信息 435 | +0x4b0 DpcTime : Uint4B//统计信息 436 | +0x4b4 DebugDpcTime : Uint4B//统计信息 437 | +0x4b8 InterruptTime : Uint4B//统计信息 438 | +0x4bc AdjustDpcThreshold : Uint4B 439 | +0x4c0 PageColor : Uint4B 440 | +0x4c4 SkipTick : Uint4B 441 | +0x4c8 MultiThreadSetBusy : UChar 442 | +0x4c9 Spare2 : [3] UChar 443 | +0x4cc ParentNode : Ptr32 _KNODE 444 | +0x4d0 MultiThreadProcessorSet : Uint4B 445 | +0x4d4 MultiThreadSetMaster : Ptr32 _KPRCB 446 | +0x4d8 ThreadStartCount : [2] Uint4B 447 | +0x4e0 CcFastReadNoWait : Uint4B 448 | +0x4e4 CcFastReadWait : Uint4B 449 | +0x4e8 CcFastReadNotPossible : Uint4B 450 | +0x4ec CcCopyReadNoWait : Uint4B 451 | +0x4f0 CcCopyReadWait : Uint4B 452 | +0x4f4 CcCopyReadNoWaitMiss : Uint4B 453 | +0x4f8 KeAlignmentFixupCount : Uint4B 454 | +0x4fc KeContextSwitches : Uint4B 455 | +0x500 KeDcacheFlushCount : Uint4B 456 | +0x504 KeExceptionDispatchCount : Uint4B 457 | +0x508 KeFirstLevelTbFills : Uint4B 458 | +0x50c KeFloatingEmulationCount : Uint4B 459 | +0x510 KeIcacheFlushCount : Uint4B 460 | +0x514 KeSecondLevelTbFills : Uint4B 461 | +0x518 KeSystemCalls : Uint4B 462 | +0x51c SpareCounter0 : [1] Uint4B 463 | +0x520 PPLookasideList : [16] _PP_LOOKASIDE_LIST 464 | +0x5a0 PPNPagedLookasideList : [32] _PP_LOOKASIDE_LIST 465 | +0x6a0 PPPagedLookasideList : [32] _PP_LOOKASIDE_LIST 466 | +0x7a0 PacketBarrier : Uint4B 467 | +0x7a4 ReverseStall : Uint4B 468 | +0x7a8 IpiFrame : Ptr32 Void 469 | +0x7ac PrcbPad2 : [52] UChar 470 | +0x7e0 CurrentPacket : [3] Ptr32 Void 471 | +0x7ec TargetSet : Uint4B 472 | +0x7f0 WorkerRoutine : Ptr32 void 473 | +0x7f4 IpiFrozen : Uint4B 474 | +0x7f8 PrcbPad3 : [40] UChar 475 | +0x820 RequestSummary : Uint4B 476 | +0x824 SignalDone : Ptr32 _KPRCB 477 | +0x828 PrcbPad4 : [56] UChar 478 | +0x860 DpcListHead : _LIST_ENTRY 479 | +0x868 DpcStack : Ptr32 Void 480 | +0x86c DpcCount : Uint4B 481 | +0x870 DpcQueueDepth : Uint4B 482 | +0x874 DpcRoutineActive : Uint4B 483 | +0x878 DpcInterruptRequested : Uint4B 484 | +0x87c DpcLastCount : Uint4B 485 | +0x880 DpcRequestRate : Uint4B 486 | +0x884 MaximumDpcQueueDepth : Uint4B 487 | +0x888 MinimumDpcRate : Uint4B 488 | +0x88c QuantumEnd : Uint4B 489 | +0x890 PrcbPad5 : [16] UChar 490 | +0x8a0 DpcLock : Uint4B 491 | +0x8a4 PrcbPad6 : [28] UChar 492 | +0x8c0 CallDpc : _KDPC 493 | +0x8e0 ChainedInterruptList : Ptr32 Void 494 | +0x8e4 LookasideIrpFloat : Int4B 495 | +0x8e8 SpareFields0 : [6] Uint4B 496 | +0x900 VendorString : [13] UChar 497 | +0x90d InitialApicId : UChar 498 | +0x90e LogicalProcessorsPerPhysicalProcessor : UChar//每个物理处理器有几个逻辑处理器 499 | +0x910 MHz : Uint4B//频率 500 | +0x914 FeatureBits : Uint4B 501 | +0x918 UpdateSignature : _LARGE_INTEGER 502 | +0x920 NpxSaveArea : _FX_SAVE_AREA 503 | +0xb30 PowerState : _PROCESSOR_POWER_STATE 504 | ``` 505 | 506 | 507 | 508 | ## 逆向分析 KiSystemService 509 | 510 | `KiSystemService`这个函数也就是中断的时候,`0x2E`的内容 511 | 512 | ```asm 513 | .text:004067D1 _KiSystemService proc near ; CODE XREF: ZwAcceptConnectPort(x,x,x,x,x,x)+C↓p 514 | .text:004067D1 ; ZwAccessCheck(x,x,x,x,x,x,x,x)+C↓p ... 515 | .text:004067D1 516 | .text:004067D1 arg_0 = dword ptr 4 517 | .text:004067D1 518 | .text:004067D1 push 0 519 | .text:004067D3 push ebp ; push的0是压入0x064 ErrCode的位置 520 | .text:004067D4 push ebx ; +0x05c Ebx 521 | .text:004067D5 push esi ; +0x058 Esi 522 | .text:004067D6 push edi ; +0x054 Edi 523 | .text:004067D7 push fs ; +0x050 SegFs 524 | .text:004067D9 mov ebx, 30h ; '0' ; 为FS寄存器赋值,指向KPCR结构体 525 | .text:004067DE mov fs, ebx ; 将段选择子0x30查询GDT这张表,找到对应的段描述符,把段描述符加载到FS寄存器 526 | .text:004067DE ; 527 | .text:004067DE ; 0x30: // 0011 0000 528 | .text:004067DE ; 索引为6的段描述符,查GDT表 529 | .text:004067DE ; 本机中idx为6的值:ffc093df`f0000001 530 | .text:004067DE ; fs.base = ffdff000,指向当前CPU的KPCR结构 531 | .text:004067E0 push large dword ptr fs:0 ; 保存旧的 ExceptionList,然后把新的清成-1 532 | .text:004067E7 mov large dword ptr fs:0, 0FFFFFFFFh 533 | .text:004067F2 mov esi, large fs:124h ; esi 指向 CurrentThread,当前CPU所执行线程的_ETHREAD 534 | .text:004067F9 push dword ptr [esi+140h] ; 保存 CurrentThread.PreviousMode(先前模式) 535 | .text:004067F9 ; PreviousMode = 0 表示从0环调用过来 536 | .text:004067F9 ; PreviousMode = 1 表示从3环调用过来 537 | .text:004067FF sub esp, 48h ; esp 指向 _KTRAP_FRAME 538 | .text:00406802 mov ebx, [esp+68h+arg_0] ; 取出esp+0x6C,也就是3环压入的参数CS 539 | .text:00406806 and ebx, 1 ; 0环最低位为0,3环最低位为1 540 | .text:00406809 mov [esi+140h], bl ; 填写新的“先前模式” 541 | .text:0040680F mov ebp, esp ; ESP == EBP ==_KTRAP_FRAME 542 | .text:00406811 mov ebx, [esi+134h] ; EBX现在是_KTRAP_FRAME 543 | .text:00406817 mov [ebp+3Ch], ebx ; 将_KTRAP_FRAME中的TrapFrame暂时存到这里,之后 544 | .text:00406817 ; mov edx, [ebp+3Ch] 545 | .text:00406817 ; 会将这个值取出来重新赋给_KTRAP_FRAME的TrapFrame 546 | .text:0040681A mov [esi+134h], ebp ; CurrentThread.TrapFrame 指向当前 _KTRAP_FRAME 547 | .text:00406820 cld ; 将标志寄存器Flag的方向标志位DF清零 548 | .text:00406821 mov ebx, [ebp+60h] ; 3环ebp 549 | .text:00406824 mov edi, [ebp+68h] ; 3环eip 550 | .text:00406827 mov [ebp+0Ch], edx ; _KTRAP_FRAME.DbgArgPointer = edx 551 | .text:00406827 ; 这一步是保存3环API参数指针 552 | .text:0040682A mov dword ptr [ebp+8], 0BADB0D00h 553 | .text:00406831 mov [ebp+0], ebx ; _KTRAP_FRAME.DbgEbp = _KTRAP_FRAME.Ebp 554 | .text:00406834 mov [ebp+4], edi ; _KTRAP_FRAME.DbgEip = _KTRAP_FRAME.Eip 555 | .text:00406837 test byte ptr [esi+2Ch], 0FFh 556 | .text:0040683B jnz Dr_kss_a ; 测试 CurrentThread.DebugActive 557 | .text:0040683B ; 如果正被调试,保存调试相关的寄存器到 _KTRAP_FRAME 558 | .text:00406841 559 | .text:00406841 loc_406841: ; CODE XREF: Dr_kss_a+10↑j 560 | .text:00406841 ; Dr_kss_a+7C↑j 561 | .text:00406841 sti ; 允许中断 562 | .text:00406842 jmp loc_406932 563 | .text:00406842 _KiSystemService endp 564 | ``` 565 | 566 | # 005.API函数的调用过程(系统服务表) 567 | 568 | 上节内容:进0环后,3环的各种寄存器都会保留到_Trap_Frame结构体中 569 | 570 | 本节内容: 571 | 572 | - 如何根据系统服务号(eax中存储)找到要执行的内核函数? 573 | - 调用时参数是存储到3环的堆栈,如何传递给内核函数? 574 | 575 | SystemServiceTable 系统服务表 576 | 577 | ![image-20230107230553238](./03系统调用/image-20230107230553238.png) 578 | 579 | 这个表在`_KTHREAD`的偏移为0xE0的位置。 580 | 581 | 如何判断是上面还是下面那张表: 582 | 583 | ![image-20230107230710291](./03系统调用/image-20230107230710291.png) 584 | 585 | 这个是`_KiFastCallEntry`,KiSystemService的最后直接到了`0x00406932`的位置 586 | 587 | ```asm 588 | .text:0040689F _KiFastCallEntry proc near ; DATA XREF: _KiTrap01+71↓o 589 | .text:0040689F ; KiLoadFastSyscallMachineSpecificRegisters(x)+24↓o 590 | .text:0040689F 591 | .text:0040689F var_B = byte ptr -0Bh 592 | .text:0040689F 593 | .text:0040689F ; FUNCTION CHUNK AT .text:0040686C SIZE 00000024 BYTES 594 | .text:0040689F 595 | .text:0040689F mov ecx, 23h ; '#' 596 | .text:004068A4 push 30h ; '0' 597 | .text:004068A6 pop fs 598 | .text:004068A8 mov ds, ecx 599 | .text:004068AA mov es, ecx 600 | .text:004068AC mov ecx, large fs:40h 601 | .text:004068B3 mov esp, [ecx+4] 602 | .text:004068B6 push 23h ; '#' 603 | .text:004068B8 push edx 604 | .text:004068B9 pushf 605 | .text:004068BA 606 | .text:004068BA loc_4068BA: ; CODE XREF: _KiFastCallEntry2+23↑j 607 | .text:004068BA push 2 608 | .text:004068BC add edx, 8 609 | .text:004068BF popf 610 | .text:004068C0 or [esp+0Ch+var_B], 2 611 | .text:004068C5 push 1Bh 612 | .text:004068C7 push dword ptr ds:0FFDF0304h 613 | .text:004068CD push 0 614 | .text:004068CF push ebp 615 | .text:004068D0 push ebx 616 | .text:004068D1 push esi 617 | .text:004068D2 push edi 618 | .text:004068D3 mov ebx, large fs:1Ch 619 | .text:004068DA push 3Bh ; ';' 620 | .text:004068DC mov esi, [ebx+124h] 621 | .text:004068E2 push dword ptr [ebx] 622 | .text:004068E4 mov dword ptr [ebx], 0FFFFFFFFh 623 | .text:004068EA mov ebp, [esi+18h] 624 | .text:004068ED push 1 625 | .text:004068EF sub esp, 48h 626 | .text:004068F2 sub ebp, 29Ch 627 | .text:004068F8 mov byte ptr [esi+140h], 1 628 | .text:004068FF cmp ebp, esp 629 | .text:00406901 jnz loc_40686C 630 | .text:00406907 and dword ptr [ebp+2Ch], 0 631 | .text:0040690B test byte ptr [esi+2Ch], 0FFh 632 | .text:0040690F mov [esi+134h], ebp 633 | .text:00406915 jnz Dr_FastCallDrSave 634 | .text:0040691B 635 | .text:0040691B loc_40691B: ; CODE XREF: Dr_FastCallDrSave+10↑j 636 | .text:0040691B ; Dr_FastCallDrSave+7C↑j 637 | .text:0040691B mov ebx, [ebp+60h] 638 | .text:0040691E mov edi, [ebp+68h] 639 | .text:00406921 mov [ebp+0Ch], edx 640 | .text:00406924 mov dword ptr [ebp+8], 0BADB0D00h 641 | .text:0040692B mov [ebp+0], ebx 642 | .text:0040692E mov [ebp+4], edi 643 | .text:00406931 sti 644 | .text:00406932 645 | .text:00406932 loc_406932: ; CODE XREF: _KiBBTUnexpectedRange+18↑j 646 | .text:00406932 ; _KiSystemService+71↑j 647 | .text:00406932 mov edi, eax ; 取出3环传进来的系统调用号 648 | .text:00406934 shr edi, 8 ; 右移8位 649 | .text:00406937 and edi, 30h ; 检测系统调用号12位 650 | .text:00406937 ; 如果等于1,那么 edi == 0x10 651 | .text:00406937 ; 如果等于0,那么 edi == 0x00 652 | .text:0040693A mov ecx, edi 653 | .text:0040693C add edi, [esi+0E0h] ; edi += CurrentThread.ServiceTable 654 | .text:0040693C ; 此时 edi 指向了API对应的系统服务表 655 | .text:0040693C ; 656 | .text:0040693C ; 0x10 刚好是系统服务表的大小 657 | .text:0040693C ; 系统服务表有 ServiceTable, Count, ServiceLimit 和 ArgmentTable 658 | .text:0040693C ; 4项共0x10字节,所以通过这里的代码也可以推断,内核和win32k.sys的系统服务表是连续的 659 | .text:0040693C ; 第一张是内核的,第二张是win32k.sys的 660 | .text:00406942 mov ebx, eax ; ebx = 系统调用号 661 | .text:00406944 and eax, 0FFFh ; eax = 系统服务表下标 662 | .text:00406949 cmp eax, [edi+8] 663 | .text:0040694C jnb _KiBBTUnexpectedRange ; 检查系统调用号是否超过系统服务表的范围,超过就跳到异常处理 664 | .text:00406952 cmp ecx, 10h 665 | .text:00406955 jnz short loc_406972 ; 跳转条件:系统服务(ntdll.dll 的API) 666 | .text:00406955 ; 不跳转条件:图形及用户界面(gdi.dll 的API) 667 | .text:00406957 mov ecx, large fs:18h 668 | .text:0040695E xor ebx, ebx 669 | .text:0040695E _KiFastCallEntry endp ; sp-analysis failed 670 | .text:0040695E 671 | .text:00406960 672 | .text:00406960 ; =============== S U B R O U T I N E ======================================= 673 | .text:00406960 674 | .text:00406960 675 | .text:00406960 ; _DWORD __stdcall KiSystemServiceAccessTeb() 676 | .text:00406960 _KiSystemServiceAccessTeb@0 proc near ; DATA XREF: KiPreprocessAccessViolation(x,x,x)+3D↓o 677 | .text:00406960 678 | .text:00406960 ; FUNCTION CHUNK AT .text:00406B4F SIZE 0000000A BYTES 679 | .text:00406960 680 | .text:00406960 or ebx, [ecx+0F70h] 681 | .text:00406966 jz short loc_406972 ; _KCPR.KPRCB.KeSystemCalls += 1, 系统调用计数加1 682 | .text:00406968 push edx 683 | .text:00406969 push eax 684 | .text:0040696A call ds:_KeGdiFlushUserBatch 685 | .text:00406970 pop eax 686 | .text:00406971 pop edx 687 | .text:00406972 688 | .text:00406972 loc_406972: ; CODE XREF: _KiFastCallEntry+B6↑j 689 | .text:00406972 ; KiSystemServiceAccessTeb()+6↑j 690 | .text:00406972 inc large dword ptr fs:638h ; _KCPR.KPRCB.KeSystemCalls += 1, 系统调用计数加1 691 | .text:00406979 mov esi, edx ; esi = edx = 3环参数指针 692 | .text:0040697B mov ebx, [edi+0Ch] ; ebx 指向函数参数表 693 | .text:0040697B ; eax 是系统调用号 694 | .text:0040697E xor ecx, ecx 695 | .text:00406980 mov cl, [eax+ebx] ; cl = 参数字节数 696 | .text:00406983 mov edi, [edi] ; edi 指向函数地址表 697 | .text:00406985 mov ebx, [edi+eax*4] ; ebx 指向0环函数 698 | .text:00406988 sub esp, ecx ; 从这句开始,到call为止,完成了复制3环参数的工作 699 | .text:00406988 ; 这句是模拟压栈操作 700 | .text:0040698A shr ecx, 2 ; 参数字节数 / 4,得到参数个数 701 | .text:0040698D mov edi, esp 702 | .text:0040698F test byte ptr [ebp+72h], 2 703 | .text:00406993 jnz short loc_40699B ; 越界检查 704 | .text:00406993 ; 如果 esi(3环参数指针)大于等于 0x7fff0000,则返回 c0000005 异常 705 | .text:00406995 test byte ptr [ebp+6Ch], 1 706 | .text:00406999 jz short _KiSystemServiceCopyArguments@0 ; 复制参数:复制 esi 到 edi,每次复制4字节,次数由 ecx 决定 707 | .text:00406999 ; 方向由DF决定,DF=0,故每次复制后,edi 和 esi 都加4 708 | .text:0040699B 709 | .text:0040699B loc_40699B: ; CODE XREF: KiSystemServiceAccessTeb()+33↑j 710 | .text:0040699B cmp esi, ds:_MmUserProbeAddress ; 越界检查 711 | .text:0040699B ; 如果 esi(3环参数指针)大于等于 0x7fff0000,则返回 c0000005 异常 712 | .text:004069A1 jnb loc_406B4F 713 | .text:004069A1 _KiSystemServiceAccessTeb@0 endp 714 | .text:004069A1 715 | .text:004069A7 716 | .text:004069A7 ; =============== S U B R O U T I N E ======================================= 717 | .text:004069A7 718 | .text:004069A7 ; 复制参数:复制 esi 到 edi,每次复制4字节,次数由 ecx 决定 719 | .text:004069A7 ; 方向由DF决定,DF=0,故每次复制后,edi 和 esi 都加4 720 | .text:004069A7 721 | .text:004069A7 ; _DWORD __stdcall KiSystemServiceCopyArguments() 722 | .text:004069A7 _KiSystemServiceCopyArguments@0 proc near 723 | .text:004069A7 ; CODE XREF: KiSystemServiceAccessTeb()+39↑j 724 | .text:004069A7 ; DATA XREF: KiPreprocessAccessViolation(x,x,x):loc_4628DF↓o 725 | .text:004069A7 rep movsd 726 | .text:004069A9 call ebx ; 复制参数:复制 esi 到 edi,每次复制4字节,次数由 ecx 决定 727 | .text:004069A9 _KiSystemServiceCopyArguments@0 endp ; 方向由DF决定,DF=0,故每次复制后,edi 和 esi 都加4 728 | .text:004069A9 ; 调用内核函数 729 | .text:004069AB 730 | ``` 731 | 732 | 733 | 734 | 735 | 736 | # 006.API函数的调用过程(SSDT) 737 | 738 | 本节通过其他方式来访问系统服务表. 739 | 740 | SSDT 的全称是 System Services Descriptor Table,系统服务描述符表 741 | 742 | ``` 743 | kd> dd KeServiceDescriptorTable(SSDT) 744 | 导出的 声明一下就可以使用了 745 | 746 | kd> dd KeServiceDescriptorTableShadow(SSDT Shadow) 747 | 未导出 需要用其他的方式来查找 748 | ``` 749 | 750 | 上面的是导出的,下面是未导出的,可以看到导出的里面只有一张表有值,其余三张没有值,如果想看第二张表的话可以看未导出的: 751 | 752 | ![image-20230107234334197](./03系统调用/image-20230107234334197.png) 753 | 754 | 这里使用前面的那个函数进入0环需要的系统服务号(BA),这里要*4,每个是4字节(其实下面的那个函数就是`nt!NtReadVirtualMemory`这个函数): 755 | 756 | ![image-20230107235014722](./03系统调用/image-20230107235014722.png) 757 | 758 | 所需要的参数的字节数,0x14,也就是20字节: 759 | 760 | ![image-20230107235309282](./03系统调用/image-20230107235309282.png) 761 | -------------------------------------------------------------------------------- /03系统调用/image-20230106134533807.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/03系统调用/image-20230106134533807.png -------------------------------------------------------------------------------- /03系统调用/image-20230106134646722.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/03系统调用/image-20230106134646722.png -------------------------------------------------------------------------------- /03系统调用/image-20230106140227852.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/03系统调用/image-20230106140227852.png -------------------------------------------------------------------------------- /03系统调用/image-20230106140509018.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/03系统调用/image-20230106140509018.png -------------------------------------------------------------------------------- /03系统调用/image-20230106141108580.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/03系统调用/image-20230106141108580.png -------------------------------------------------------------------------------- /03系统调用/image-20230106142000444.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/03系统调用/image-20230106142000444.png -------------------------------------------------------------------------------- /03系统调用/image-20230106142020461.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/03系统调用/image-20230106142020461.png -------------------------------------------------------------------------------- /03系统调用/image-20230106143004394.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/03系统调用/image-20230106143004394.png -------------------------------------------------------------------------------- /03系统调用/image-20230107134858939.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/03系统调用/image-20230107134858939.png -------------------------------------------------------------------------------- /03系统调用/image-20230107230553238.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/03系统调用/image-20230107230553238.png -------------------------------------------------------------------------------- /03系统调用/image-20230107230710291.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/03系统调用/image-20230107230710291.png -------------------------------------------------------------------------------- /03系统调用/image-20230107234334197.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/03系统调用/image-20230107234334197.png -------------------------------------------------------------------------------- /03系统调用/image-20230107235014722.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/03系统调用/image-20230107235014722.png -------------------------------------------------------------------------------- /03系统调用/image-20230107235309282.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/03系统调用/image-20230107235309282.png -------------------------------------------------------------------------------- /04进程与线程/image-20230119203755480.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/04进程与线程/image-20230119203755480.png -------------------------------------------------------------------------------- /04进程与线程/image-20230218163344642.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/04进程与线程/image-20230218163344642.png -------------------------------------------------------------------------------- /04进程与线程/image-20230218165731076.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/04进程与线程/image-20230218165731076.png -------------------------------------------------------------------------------- /04进程与线程/image-20230218165835614.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/04进程与线程/image-20230218165835614.png -------------------------------------------------------------------------------- /04进程与线程/image-20230218174027106.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/04进程与线程/image-20230218174027106.png -------------------------------------------------------------------------------- /04进程与线程/image-20230218205639146.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/04进程与线程/image-20230218205639146.png -------------------------------------------------------------------------------- /04进程与线程/image-20230219125142968.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/04进程与线程/image-20230219125142968.png -------------------------------------------------------------------------------- /04进程与线程/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0t3YW5zeQ==,size_16,color_FFFFFF,t_70#pic_center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/04进程与线程/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0t3YW5zeQ==,size_16,color_FFFFFF,t_70#pic_center.png -------------------------------------------------------------------------------- /05句柄表.md: -------------------------------------------------------------------------------- 1 | [toc] 2 | 3 | 4 | 5 | # 01.句柄表 6 | 7 | 1. 当一个进程创建或者打开一个内核对象时,将获得一个句柄,通过这个句柄可以访问对应的内核对象 8 | 9 | 2. 句柄表存储在零环,一个进程使用了几个句柄,在该进程的句柄表中就会存储几个句柄 10 | 11 | 3. 所有的句柄所对应的内核对象,都包含在**_OBJECT_HEADER** 中,真正的内核对象保存在 **_OBJECT_HEADER +0x018 body** 的位置(`ETHREAD`和`EPROCESS`也都放在这个位置) 12 | 13 | ```sh 14 | kd> dt _OBJECT_HEADER 15 | nt!_OBJECT_HEADER 16 | +0x000 PointerCount : Int4B 17 | +0x004 HandleCount : Int4B 18 | +0x004 NextToFree : Ptr32 Void 19 | +0x008 Type : Ptr32 _OBJECT_TYPE 20 | +0x00c NameInfoOffset : UChar 21 | +0x00d HandleInfoOffset : UChar 22 | +0x00e QuotaInfoOffset : UChar 23 | +0x00f Flags : UChar 24 | +0x010 ObjectCreateInfo : Ptr32 _OBJECT_CREATE_INFORMATION 25 | +0x010 QuotaBlockCharged : Ptr32 Void 26 | +0x014 SecurityDescriptor : Ptr32 Void 27 | +0x018 Body : _QUAD 28 | ``` 29 | 30 | 1. 窗口、字体、笔刷等句柄与本章所学句柄是两码事 31 | 32 | 2. 创建句柄不等同于打开句柄,当创建的时候,操作系统会在零环为内核对象分配一个结构体(例如CreateEvent),如果自己或他人打开了这个内核对象(例如OpenProcess),那么将不会再次为这个内核对象分配一个结构体,而是返回一个句柄的索引值 33 | 34 | 3. 若同一个内核对象被引用了100次,那么在句柄表中就会存储100个内核对象的地址 35 | 36 | 4. 句柄的值并非如上图所显示的只占4个字节,而是占8个字节,但是句柄表的值仍然按照4个字节进行计算 37 | 38 | 计算:`handle = index / 4 * 8` 39 | 40 | ## 查看句柄表 41 | 42 | 示例代码: 43 | 44 | ```c 45 | #include 46 | #include 47 | 48 | int main() 49 | { 50 | DWORD PID; 51 | HANDLE hPro = NULL; 52 | HWND hWnd = ::FindWindow(NULL, "计算器"); 53 | ::GetWindowThreadProcessId(hWnd, &PID); 54 | for(int i=0; i<100 ;i++) 55 | { 56 | hPro = ::OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE, TRUE, PID); 57 | printf("句柄:%x\n", hPro); 58 | } 59 | getchar(); 60 | return 0; 61 | } 62 | ``` 63 | 64 | 运行结果: 65 | 66 | ![image-20230219172158354](./05句柄表/image-20230219172158354.png) 67 | 68 | 69 | 70 | ```sh 71 | kd> !process 0 0 72 | ... 73 | Failed to get VadRoot 74 | PROCESS 8613b688 SessionId: 0 Cid: 07b4 Peb: 7ffde000 ParentCid: 07ac 75 | DirBase: 06bc0340 ObjectTable: e35367b8 HandleCount: 116. 76 | Image: test.exe 77 | ------------------------------------------------------------------------------ 78 | kd> dt _EPROCESS 8613b688 79 | ntdll!_EPROCESS 80 | ... 81 | +0x0c4 ObjectTable : 0xe35367b8 _HANDLE_TABLE //这里 82 | ... 83 | ------------------------------------------------------------------------------ 84 | kd> dt _HANDLE_TABLE 0xe35367b8 85 | nt_exe!_HANDLE_TABLE 86 | +0x000 TableCode : 0xe1251000 //这里 87 | +0x004 QuotaProcess : 0x8613b688 _EPROCESS 88 | +0x008 UniqueProcessId : 0x000007b4 Void 89 | +0x00c HandleTableLock : [4] _EX_PUSH_LOCK 90 | +0x01c HandleTableList : _LIST_ENTRY [ 0x80565ba8 - 0xe2f363b4 ] 91 | +0x024 HandleContentionEvent : _EX_PUSH_LOCK 92 | +0x028 DebugInfo : (null) 93 | +0x02c ExtraInfoPages : 0n0 94 | +0x030 FirstFree : 0x63c 95 | +0x034 LastFree : 0 96 | +0x038 NextHandleNeedingPool : 0x800 97 | +0x03c HandleCount : 0n116 98 | +0x040 Flags : 0 99 | +0x040 StrictFIFO : 0y0 100 | ------------------------------------------------------------------------------ 101 | kd> dq 0xe1251000 102 | ReadVirtual: e1251000 not properly sign extended 103 | e1251000 fffffffe`00000000 00000000`00000000 104 | e1251010 00000004`00000000 00000008`00000000 105 | e1251020 0000000c`00000000 00000010`00000000 106 | e1251030 00000014`00000000 00000018`00000000 107 | e1251040 0000001c`00000000 00000020`00000000 108 | e1251050 00000024`00000000 00000028`00000000 109 | e1251060 0000002c`00000000 00000030`00000000 110 | e1251070 00000034`00000000 00000038`00000000 111 | ``` 112 | 113 | ## 句柄表结构 114 | 115 | 116 | 117 | ```sh 118 | kd> dt _HANDLE_TABLE 119 | nt_exe!_HANDLE_TABLE 120 | +0x000 TableCode : Uint4B 121 | +0x004 QuotaProcess : Ptr32 _EPROCESS 122 | +0x008 UniqueProcessId : Ptr32 Void 123 | +0x00c HandleTableLock : [4] _EX_PUSH_LOCK 124 | +0x01c HandleTableList : _LIST_ENTRY 125 | +0x024 HandleContentionEvent : _EX_PUSH_LOCK 126 | +0x028 DebugInfo : Ptr32 _HANDLE_TRACE_DEBUG_INFO 127 | +0x02c ExtraInfoPages : Int4B 128 | +0x030 FirstFree : Uint4B 129 | +0x034 LastFree : Uint4B 130 | +0x038 NextHandleNeedingPool : Uint4B 131 | +0x03c HandleCount : Int4B 132 | +0x040 Flags : Uint4B 133 | +0x040 StrictFIFO : Pos 0, 1 Bit 134 | ``` 135 | 136 | `TableCode`就是的句柄表,结构如下: 137 | 138 | ![img](./05句柄表/2520882-20220119172827300-822756739.png) 139 | 140 | 1. 这一块共计两个字节,高位字节是给`SetHandleInformation`这个函数用的,比如写成如下形式,那么这个位置将被写入`0x02` 141 | 142 | ```c 143 | SetHandleInformation(Handle,HANDLE_FLAG_PROTECT_FROM_CLOSE,HANDLE_FLAG_PROTECT_FROM_CLOSE); 144 | //HANDLE_FLAG_PROTECT_FROM_CLOSE宏的值为0x00000002,取最低字节,最终这块是0x0200 145 | ``` 146 | 147 | 2. 这块是访问掩码,是给**OpenProess**这个函数用的,具体的存的值就是这个函数的第一个参数的值。 148 | 149 | 3. ③ 和 ④ 这两个块共计四个字节,其中`bit0-bit2`存的是这个句柄的属性,其中`bit2`和`bit0`默认为`0`和`1`;`bit1`表示的函数是该句柄是否可继承,`OpenProcess`的第二个参数与`bit1`有关,`bit31-bit3`则是存放的该内核对象在内核中的具体的地址。 150 | 151 | ```sh 152 | //代码中第一个句柄是7cc 153 | kd> dq 0xe1251000+7cc*2 154 | ReadVirtual: e1251f98 not properly sign extended 155 | e1251f98 0000003a`85fcc00b 000f01ff`86187571 156 | e1251fa8 000f037f`86408651 021f0003`85f98551 157 | e1251fb8 020f003f`e2e7dc19 000f037f`86408651 158 | e1251fc8 001f0003`85fc21d1 00100003`85fbb221 159 | e1251fd8 021f0001`e1132cc9 000f000f`e135f6e9 160 | e1251fe8 00100003`8613b5f9 00000003`e156d471 161 | e1251ff8 000f0003`e1001109 63416553`04810600 162 | e1252008 00000000`e11aec30 864cd650`00000000 163 | 164 | kd> dq 0xe1251000+640*2 165 | ReadVirtual: e1251c80 not properly sign extended 166 | e1251c80 0000003a`85fcc00b 0000003a`85fcc00b 167 | e1251c90 0000003a`85fcc00b 0000003a`85fcc00b 168 | e1251ca0 0000003a`85fcc00b 0000003a`85fcc00b 169 | e1251cb0 0000003a`85fcc00b 0000003a`85fcc00b 170 | e1251cc0 0000003a`85fcc00b 0000003a`85fcc00b 171 | e1251cd0 0000003a`85fcc00b 0000003a`85fcc00b 172 | e1251ce0 0000003a`85fcc00b 0000003a`85fcc00b 173 | e1251cf0 0000003a`85fcc00b 0000003a`85fcc00b 174 | ``` 175 | 176 | 下面是置句柄表高两字节为0x20 177 | 178 | ```c 179 | #include 180 | #include 181 | 182 | int main() 183 | { 184 | DWORD PID; 185 | HANDLE hPro = NULL; 186 | HWND hWnd = ::FindWindow(NULL, "计算器"); 187 | ::GetWindowThreadProcessId(hWnd, &PID); 188 | for(int i=0; i<100 ;i++) 189 | { 190 | hPro = ::OpenProcess(PROCESS_CREATE_THREAD, TRUE, PID); 191 | 192 | printf("句柄:%x\n", hPro); 193 | } 194 | //HANDLE_FLAG_PROTECT_FROM_CLOSE:句柄不可用CloseHandle关闭 195 | SetHandleInformation(hPro, HANDLE_FLAG_PROTECT_FROM_CLOSE, HANDLE_FLAG_PROTECT_FROM_CLOSE); 196 | getchar(); 197 | return 0; 198 | } 199 | ``` 200 | 201 | windbg中: 202 | 203 | ```sh 204 | kd> dq 0xe11cf000+640*2 205 | ReadVirtual: e11cfc80 not properly sign extended 206 | e11cfc80 02000002`85fcc00b 00000002`85fcc00b 207 | e11cfc90 00000002`85fcc00b 00000002`85fcc00b 208 | e11cfca0 00000002`85fcc00b 00000002`85fcc00b 209 | e11cfcb0 00000002`85fcc00b 00000002`85fcc00b 210 | e11cfcc0 00000002`85fcc00b 00000002`85fcc00b 211 | e11cfcd0 00000002`85fcc00b 00000002`85fcc00b 212 | e11cfce0 00000002`85fcc00b 00000002`85fcc00b 213 | e11cfcf0 00000002`85fcc00b 00000002`85fcc00b 214 | ``` 215 | 216 | ### 根据句柄定位内核对象 217 | 218 | 此时该地址指向`_OBJECT_HEADER`,想查看真正的内核对象结构体还要加上0x18 219 | 220 | ```sh 221 | //根据句柄查找对应的结构体地址: 222 | /清理后三位bit,后四个字节为地址:85fcc008 223 | kd> dt _EPROCESS 85fcc008+18 224 | nt_exe!_EPROCESS 225 | ... 226 | +0x174 ImageFileName : [16] "calc.exe" 227 | ... 228 | ``` 229 | 230 | # 02 全局句柄表 231 | 232 | 233 | 234 | ## 全局句柄表 235 | 236 | 1. 进程的句柄表是私有的,每个进程都有一个自己的句柄表。 237 | 2. 除此之外,系统还有一个全局句柄表:`PsdCidTable` ,为 **_HANDLE_TABLE** 结构,所有的进程和线程无论无论是否打开,都在这个表中 238 | 3. 每个进程和线程都有一个唯一的编号:**PID**和**CID** 这两个值其实就是全局句柄表中的索引 239 | 4. 进程和线程的查询,主要是以下三个函数,按照给定的PID或CID从`PspCidTable`从查找相应的进线程对象: 240 | 241 | - `PsLookupProcessThreadByCid()` 242 | - `PsLookupProcessByProcessId()` 243 | - `PsLookupThreadByThreadId()` 244 | 245 | ## 全局句柄表结构 246 | 247 | 248 | 249 | 1. 若TableCode的低两位值为0,说明`handle_max = 4KB / 8 = 512`,此时,句柄表为一级句柄表 250 | 2. 若打开句柄数量超过512个,TableCode的低两位值就会置为1,此时,句柄表变为两级句柄表。第一级句柄表中每个成员存储着第二级句柄表的地址,第二级句柄表中才真正存储着内核对象的地址,`handle_max = 1024 * 512` 251 | 3. 若打开句柄数量超过1024 * 512个,TableCode低两位的值就会置为2,此时,句柄表变为三级句柄表,第一级为地址,第二级也为地址,第三级才是句柄,`handle_max = 1024 * 1024 * 512` 252 | 4. 全局句柄表存储了所有 `EPROCESS` 和 `ETHREAD`。和进程的句柄表不同,全局句柄表项低32位指向的就是内核对象,而非 `OBJECT_HEADER`. 253 | 254 | ![image-20230219180656748](./05句柄表/image-20230219180656748.png) 255 | 256 | ### 在WinDbg中查看全局句柄表 257 | 258 | 这里还是使用计算器举例: 259 | 260 | 261 | 262 | ![image-20230219181053778](./05句柄表/image-20230219181053778.png) 263 | 264 | **index = 1900 / 4 = 0x1DB** 265 | 266 | ```sh 267 | kd> dd PspCidTable 268 | 805649c0 e1003c58 00000002 00000000 00000000 269 | 805649d0 00000000 00000000 00000000 00000000 270 | 805649e0 00000000 00000000 00000000 00000000 271 | 805649f0 00000000 00000000 00000000 00000000 272 | 80564a00 00000000 00000000 00000000 00000000 273 | 80564a10 00000000 00000000 00000000 00000000 274 | 80564a20 00000000 00000000 00000000 00000000 275 | 80564a30 00000000 00000000 00000000 00000000 276 | ------------------------------------------------------------------------------ 277 | kd> dt _HANDLE_TABLE e1003c58 278 | ntdll!_HANDLE_TABLE 279 | +0x000 TableCode : 0xe1005000 280 | +0x004 QuotaProcess : (null) 281 | +0x008 UniqueProcessId : (null) 282 | +0x00c HandleTableLock : [4] _EX_PUSH_LOCK 283 | +0x01c HandleTableList : _LIST_ENTRY [ 0xe1003c74 - 0xe1003c74 ] 284 | +0x024 HandleContentionEvent : _EX_PUSH_LOCK 285 | +0x028 DebugInfo : (null) 286 | +0x02c ExtraInfoPages : 0n0 287 | +0x030 FirstFree : 0x774 288 | +0x034 LastFree : 0x768 289 | +0x038 NextHandleNeedingPool : 0x800 290 | +0x03c HandleCount : 0n253 291 | +0x040 Flags : 1 292 | +0x040 StrictFIFO : 0y1 293 | ------------------------------------------------------------------------------ 294 | kd> dq 0xe1005000+1DB*8 295 | ReadVirtual: e1005ed8 not properly sign extended 296 | e1005ed8 00000000`8632fda1 00000000`8632f989 297 | e1005ee8 00000778`00000000 0000077c`00000000 298 | e1005ef8 00000780`00000000 0000078c`00000000 299 | e1005f08 00000000`86475ce9 00000000`864756c1 300 | e1005f18 00000790`00000000 00000794`00000000 301 | e1005f28 00000798`00000000 0000079c`00000000 302 | e1005f38 000007a0`00000000 000007a4`00000000 303 | e1005f48 000007a8`00000000 000007ac`00000000 304 | ------------------------------------------------------------------------------ 305 | kd> dt _EPROCESS 8632fda0//全局句柄表直接指向内核对象,不用加0x18 306 | nt_exe!_EPROCESS 307 | ... 308 | +0x174 ImageFileName : [16] "calc.exe" 309 | ... 310 | ``` 311 | 312 | 313 | 314 | ## 遍历全局句柄表 315 | 316 | > 编写程序,通过全局句柄表PsdCidTable,遍历所有进程(包括隐藏进程)。 317 | > 318 | > 打印全局句柄表中内核对象的所有类型 319 | > 320 | > 一、需要解决的问题: 321 | > 322 | > 1、如何通过找到全局句柄表? 323 | > 324 | > 2、如何判断是否是进程? 325 | > 326 | > 二、有用的系统函数:MmGetSystemRoutineAddress 327 | > 328 | > 这个函数用来得到导出函数的地址,优点是: 329 | > 330 | > 1、不会被IAT Hook影响(从内核模块导出表中找函数地址的) 331 | > 332 | > 2、有些内核函数虽然导出了 但并没有函数说明,无法直接使用 333 | 334 | ```c 335 | //#include 336 | //#include 337 | #include 338 | 339 | //----------------------------------------------------------------------------------------------------- 340 | //----------------------------------------------------------------------------------------------------- 341 | 342 | typedef struct _LDR_DATA_TABLE_ENTRY 343 | { 344 | LIST_ENTRY InLoadOrderLinks; 345 | LIST_ENTRY InMemoryOrderLinks; 346 | LIST_ENTRY InInitializationOrderLinks; 347 | PVOID DllBase; 348 | PVOID EntryPoint; 349 | ULONG SizeOfImage; 350 | UNICODE_STRING FullDllName; 351 | UNICODE_STRING BaseDllName; 352 | ULONG Flags; 353 | UINT16 LoadCount; 354 | UINT16 TlsIndex; 355 | LIST_ENTRY HashLinks; 356 | PVOID SectionPointer; 357 | ULONG CheckSum; 358 | ULONG TimeDateStamp; 359 | PVOID LoadedImports; 360 | PVOID EntryPointActivationContext; 361 | PVOID PatchInformation; 362 | } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; 363 | 364 | typedef struct _HANDLE_TABLE_ENTRY 365 | { 366 | 367 | // 368 | // The pointer to the object overloaded with three ob attributes bits in 369 | // the lower order and the high bit to denote locked or unlocked entries 370 | // 371 | 372 | union 373 | { 374 | 375 | PVOID Object; 376 | 377 | ULONG ObAttributes; 378 | 379 | // PHANDLE_TABLE_ENTRY_INFO InfoTable; // 用不到 380 | 381 | ULONG_PTR Value; 382 | }; 383 | 384 | // 385 | // This field either contains the granted access mask for the handle or an 386 | // ob variation that also stores the same information. Or in the case of 387 | // a free entry the field stores the index for the next free entry in the 388 | // free list. This is like a FAT chain, and is used instead of pointers 389 | // to make table duplication easier, because the entries can just be 390 | // copied without needing to modify pointers. 391 | // 392 | 393 | union 394 | { 395 | 396 | union 397 | { 398 | 399 | ACCESS_MASK GrantedAccess; 400 | 401 | struct 402 | { 403 | 404 | USHORT GrantedAccessIndex; 405 | USHORT CreatorBackTraceIndex; 406 | }; 407 | }; 408 | 409 | LONG NextFreeTableEntry; 410 | }; 411 | 412 | } HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY; 413 | 414 | typedef struct _OBJECT_TYPE 415 | { 416 | ERESOURCE Mutex; 417 | LIST_ENTRY TypeList; 418 | UNICODE_STRING Name; // Copy from object header for convenience 419 | // PVOID DefaultObject; 420 | // ULONG Index; 421 | // ULONG TotalNumberOfObjects; 422 | // ULONG TotalNumberOfHandles; 423 | // ULONG HighWaterNumberOfObjects; 424 | // ULONG HighWaterNumberOfHandles; 425 | // OBJECT_TYPE_INITIALIZER TypeInfo; 426 | // #ifdef POOL_TAGGING 427 | // ULONG Key; 428 | // #endif //POOL_TAGGING 429 | // ERESOURCE ObjectLocks[ OBJECT_LOCK_COUNT ]; 430 | } OBJECT_TYPE, *POBJECT_TYPE; 431 | 432 | typedef struct _OBJECT_HEADER 433 | { 434 | LONG PointerCount; 435 | union 436 | { 437 | LONG HandleCount; 438 | PVOID NextToFree; 439 | }; 440 | POBJECT_TYPE Type; 441 | UCHAR NameInfoOffset; 442 | UCHAR HandleInfoOffset; 443 | UCHAR QuotaInfoOffset; 444 | UCHAR Flags; 445 | union 446 | { 447 | // POBJECT_CREATE_INFORMATION ObjectCreateInfo; 448 | PVOID ObjectCreateInfo; 449 | PVOID QuotaBlockCharged; 450 | }; 451 | 452 | PSECURITY_DESCRIPTOR SecurityDescriptor; 453 | QUAD Body; 454 | } OBJECT_HEADER, *POBJECT_HEADER; 455 | 456 | //----------------------------------------------------------------------------------------------------- 457 | //----------------------------------------------------------------------------------------------------- 458 | 459 | VOID DriverUnload(PDRIVER_OBJECT pDriver); 460 | NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path); 461 | 462 | //----------------------------------------------------------------------------------------------------- 463 | //----------------------------------------------------------------------------------------------------- 464 | 465 | ULONG PspCidTable; 466 | 467 | // 驱动入口 468 | NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path) 469 | { 470 | typedef HANDLE_TABLE_ENTRY *L1P; 471 | typedef volatile L1P *L2P; 472 | typedef volatile L2P *L3P; 473 | 474 | int i, j, k; 475 | ULONG TableCode; 476 | ULONG TableLevel; 477 | L1P TableLevel1; 478 | L2P TableLevel2; 479 | L3P TableLevel3; 480 | UNICODE_STRING ProcessString; 481 | UNICODE_STRING ThreadString; 482 | ULONG HandleAddr; 483 | PEPROCESS pEprocess; 484 | PCHAR ImageFileName; 485 | POBJECT_HEADER pObjectHeader; 486 | 487 | // 使用 MmGetSystemRoutineAddress 动态获取函数地址可以防 IAT hook 488 | //这里是用MmGetSystemRoutineAddress实现的 489 | //https://www.cnblogs.com/wingsummer/p/15864867.html 490 | PspCidTable = **(PULONG *)((ULONG)PsLookupProcessByProcessId + 26); 491 | // DbgPrint("PspCidTable = %x\n",PspCidTable); 492 | TableCode = *(PULONG)PspCidTable; 493 | // DbgPrint("%x\n", TableCode); 494 | TableLevel = TableCode & 0x03; // 句柄表等级 495 | TableCode = TableCode & ~0x03; // 清除等级标志位 496 | DbgPrint("TableLevel = %x\n", TableLevel); 497 | DbgPrint("TableCode = %x\n", TableCode); 498 | 499 | RtlInitUnicodeString(&ProcessString, L"Process"); 500 | RtlInitUnicodeString(&ThreadString, L"Thread"); 501 | 502 | // 要测试这个程序,可以创建一个进程,进程创建512个线程, 503 | // 这样全局句柄表的结构就是二级的,就会进入 case 1 504 | // 如果想测试 case 2,要创建大于 1024 * 512 个内核对象 505 | switch (TableLevel) 506 | { 507 | case 0: 508 | { 509 | DbgPrint("一级句柄表...\n"); 510 | TableLevel1 = (L1P)TableCode; 511 | for (i = 0; i < 512; i++) 512 | { 513 | if (MmIsAddressValid(TableLevel1[i].Object)) 514 | { 515 | // DbgPrint("%x\n",TableLevel1[i].Object); 516 | HandleAddr = ((ULONG)(TableLevel1[i].Object) & ~0x03); 517 | pObjectHeader = (POBJECT_HEADER)(HandleAddr - 0x18); 518 | 519 | if (RtlCompareUnicodeString(&pObjectHeader->Type->Name, &ProcessString, TRUE) == 0) 520 | { 521 | // DbgPrint("EPROCESS: %x\n", HandleAddr); 522 | pEprocess = (PEPROCESS)HandleAddr; 523 | ImageFileName = (PCHAR)pEprocess + 0x174; 524 | DbgPrint("进程镜像名:%s\n", ImageFileName); 525 | } 526 | else if (RtlCompareUnicodeString(&pObjectHeader->Type->Name, &ThreadString, TRUE) == 0) 527 | { 528 | pEprocess = (PEPROCESS) * (PULONG)(HandleAddr + 0x220); 529 | ImageFileName = (PCHAR)pEprocess + 0x174; 530 | DbgPrint("----ETHREAD: %x, 所属进程:%s\n", HandleAddr, ImageFileName); 531 | } 532 | else 533 | { 534 | DbgPrint("既不是线程也不是进程 0x%x\n", HandleAddr); // 应该是不可能的...因为全局句柄表只存进程和线程 535 | } 536 | } 537 | } 538 | break; 539 | } 540 | case 1: 541 | { 542 | DbgPrint("二级句柄表...\n"); 543 | TableLevel2 = (L2P)TableCode; 544 | for (i = 0; i < 1024; i++) 545 | { 546 | if (MmIsAddressValid((PVOID)((PULONG)TableLevel2)[i])) 547 | { 548 | for (j = 0; j < 512; j++) 549 | { 550 | if (MmIsAddressValid(TableLevel2[i][j].Object)) 551 | { 552 | HandleAddr = ((ULONG)(TableLevel2[i][j].Object) & ~0x03); 553 | pObjectHeader = (POBJECT_HEADER)(HandleAddr - 0x18); 554 | if (RtlCompareUnicodeString(&pObjectHeader->Type->Name, &ProcessString, TRUE) == 0) 555 | { 556 | // DbgPrint("EPROCESS: %x\n", HandleAddr); 557 | pEprocess = (PEPROCESS)HandleAddr; 558 | ImageFileName = (PCHAR)pEprocess + 0x174; 559 | DbgPrint("进程镜像名:%s\n", ImageFileName); 560 | } 561 | else if (RtlCompareUnicodeString(&pObjectHeader->Type->Name, &ThreadString, TRUE) == 0) 562 | { 563 | pEprocess = (PEPROCESS) * (PULONG)(HandleAddr + 0x220); 564 | ImageFileName = (PCHAR)pEprocess + 0x174; 565 | DbgPrint("----ETHREAD: %x, 所属进程:%s\n", HandleAddr, ImageFileName); 566 | } 567 | else 568 | { 569 | DbgPrint("既不是线程也不是进程 0x%x\n", HandleAddr); // 应该是不可能的...因为全局句柄表只存进程和线程 570 | } 571 | } 572 | } 573 | } 574 | } 575 | break; 576 | } 577 | case 2: 578 | { 579 | DbgPrint("三级句柄表...\n"); 580 | TableLevel3 = (L3P)TableCode; 581 | for (i = 0; i < 1024; i++) 582 | { 583 | if (MmIsAddressValid((PVOID)((PULONG)TableLevel3)[i])) 584 | { 585 | for (j = 0; j < 1024; j++) 586 | { 587 | if (MmIsAddressValid((PVOID)((PULONG *)TableLevel3)[i][j])) 588 | { 589 | for (k = 0; k < 512; k++) 590 | { 591 | if (MmIsAddressValid(TableLevel3[i][j][k].Object)) 592 | { 593 | HandleAddr = ((ULONG)(TableLevel3[i][j][k].Object) & ~0x03); 594 | pObjectHeader = (POBJECT_HEADER)(HandleAddr - 0x18); 595 | if (RtlCompareUnicodeString(&pObjectHeader->Type->Name, &ProcessString, TRUE) == 0) 596 | { 597 | // DbgPrint("EPROCESS: %x\n", HandleAddr); 598 | pEprocess = (PEPROCESS)HandleAddr; 599 | ImageFileName = (PCHAR)pEprocess + 0x174; 600 | DbgPrint("进程镜像名:%s\n", ImageFileName); 601 | } 602 | else if (RtlCompareUnicodeString(&pObjectHeader->Type->Name, &ThreadString, TRUE) == 0) 603 | { 604 | pEprocess = (PEPROCESS) * (PULONG)(HandleAddr + 0x220); 605 | ImageFileName = (PCHAR)pEprocess + 0x174; 606 | DbgPrint("----ETHREAD: %x, 所属进程:%s\n", HandleAddr, ImageFileName); 607 | } 608 | else 609 | { 610 | DbgPrint("既不是线程也不是进程 0x%x\n", HandleAddr); // 应该是不可能的...因为全局句柄表只存进程和线程 611 | } 612 | } 613 | } 614 | } 615 | } 616 | } 617 | } 618 | break; 619 | } 620 | } 621 | 622 | pDriver->DriverUnload = DriverUnload; 623 | return STATUS_SUCCESS; 624 | } 625 | 626 | // 卸载驱动 627 | VOID DriverUnload(PDRIVER_OBJECT pDriver) 628 | { 629 | DbgPrint("Driver unloaded.\n"); 630 | } 631 | 632 | ULONG GetHandleFromTable(ULONG TableCode, ULONG Handle) 633 | { 634 | return 0; 635 | } 636 | 637 | ``` 638 | 639 | ![image-20230219184646960](./05句柄表/image-20230219184646960.png) 640 | 641 | 找全局句柄表也可以这么写: 642 | 643 | KPCR有一个成员,**KdVersionBlock**。这个成员非常奇妙,在他指向地址(+0x80)位置处有一个地址,这个地址指向的就是PspCidTable。 644 | 645 | (当线程运行在R0下时, FS指向的段是GDT中的0x30段.该段的长度也为4K,基地址为0xFFDFF000.该地址指向系统的处理器控制区域(KPCR)) 646 | 647 | ```c 648 | PULONG PspCidTable, TableCode; 649 | PUCHAR pEPROCESS; 650 | _asm { 651 | mov eax, fs:[0x34] 652 | mov eax, [eax + 0x80] 653 | mov eax, [eax] 654 | mov PspCidTable, eax 655 | mov eax, [eax] 656 | mov TableCode, eax 657 | } 658 | ``` 659 | 660 | ![image-20230219190424244](./05句柄表/image-20230219190424244.png) 661 | 662 | 663 | 664 | Ref: 665 | 666 | > https://drunkmars.top/2021/03/13/readme/ 667 | > 668 | > https://cataloc.gitee.io/blog/2020/04/26/%E5%85%A8%E5%B1%80%E5%8F%A5%E6%9F%84%E8%A1%A8/ 669 | > 670 | > https://blog.csdn.net/Kwansy/article/details/109853108 671 | > 672 | > https://www.cnblogs.com/wingsummer/p/15864867.html -------------------------------------------------------------------------------- /05句柄表/2520882-20220119172827300-822756739.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/05句柄表/2520882-20220119172827300-822756739.png -------------------------------------------------------------------------------- /05句柄表/image-20230219172158354.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/05句柄表/image-20230219172158354.png -------------------------------------------------------------------------------- /05句柄表/image-20230219180656748.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/05句柄表/image-20230219180656748.png -------------------------------------------------------------------------------- /05句柄表/image-20230219181053778.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/05句柄表/image-20230219181053778.png -------------------------------------------------------------------------------- /05句柄表/image-20230219184646960.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/05句柄表/image-20230219184646960.png -------------------------------------------------------------------------------- /05句柄表/image-20230219190424244.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/05句柄表/image-20230219190424244.png -------------------------------------------------------------------------------- /06事件等待.md: -------------------------------------------------------------------------------- 1 | [toc] 2 | 3 | 4 | 5 | # 01.临界区 6 | 7 | > 这个部分在驱动那一部分写了,这里就直接复制粘贴过来了 8 | 9 | 1. 并发是指多个线程在同时执行: 10 | - 单核(是分时执行,不是真正的同时) 11 | - 多核(在某一个时刻,会同时有多个线程再执行) 12 | 2. 同步则是保证在并发执行的环境中各个线程可以有序的执行 13 | 14 | ## 单行指令的同步 15 | 16 | ```c 17 | DWORD dwVal = 0; //全局变量 18 | .... 19 | .... 20 | //某个线程中 21 | dwVal++; //这行代码是否安全? 22 | ``` 23 | 24 | 实际上是**不安全**的, 25 | 26 | ```asm 27 | mov eax, [0x12345678] 28 | add eax, 1 29 | mov [0x12345678], eax 30 | ``` 31 | 32 | 程序**在执行dwVal++时**,**需要按**照顺序**执行3条汇编指令**,才能实现这条语句的功能。 33 | 34 | 现在我们来考虑一种情况,线程A和线程B均要进行dwVal++这条指令,理想状态下,这两个线程执行完后,该全局变量的值会增加2。但是**如果在线程A执行完第二条指令后**,**发生了线程切换**,情况就会变的不一样了。 35 | 36 | ```asm 37 | //线程A 38 | mov eax, [0x12345678] 39 | add eax, 1 40 | 41 | //发生线程切换 42 | //线程B 43 | mov eax, [0x12345678] 44 | add eax, 1 45 | mov [0x12345678], eax 46 | 47 | //发生线程切换 48 | //线程A 49 | mov [0x12345678], eax 50 | ``` 51 | 52 | 那单行指令安全吗? 53 | 54 | ```asm 55 | inc dword ptr ds:[0x12345678] //一行汇编指令,安全吗? 56 | ``` 57 | 58 | 这条汇编指令仅有一行,看上去不会出现上述的情况。即使线程发生切换了,也不会造成指令的重复执行。的确,在**单核**的情况下,这条指令是**安全**的,但是**多核**的情况下,还是有可能发生,不同线程同时执行这条指令的情况,所以这条指令并**不安全**。那如何才能在多核的情况下,依旧保证线程间的同步呢?那就需要用到下面介绍的这条指令了。 59 | 60 | ### Lock指令 61 | 62 | 只需要增加一个lock指令,就能让**单条指令**在多核的情况下做到同步, 63 | 64 | ```asm 65 | lock inc dword ptr ds:[0x12345678] 66 | ``` 67 | 68 | **lock指令可以锁定当前指令执行时线程所访问的内存**,上述代码执行时,会对0x12345678地址处的值进行修改,**有了lock指令**的限制,此时**其它线程**是**不能访问或修改0x12345678地址处的值**的,只有在这条指令执行完后,其余线程才可以对此地址的值进行访问或者修改。这样就避免了多核情况下,不同线程同时修改此地址处的值的情况。 69 | 70 | 像上面这样通过Lock指令进行限制,从而**不可被中断的操作**叫做**原子操作**。Windows提供了一部分API(主要位于Kernel32.dll和Ntdll.dll)供用户使用从而保证在多核情况下的线程同步: 71 | 72 | ```c 73 | //原子操作相关的API: 74 | InterlockedIncrement InterlockedExchangeAdd 75 | InterlockedDecrement InterlockedFlushSList 76 | InterlockedExchange InterlockedPopEntrySList 77 | InterlockedCompareExchange InterlockedPushEntrySList 78 | ``` 79 | 80 | ### InterlockedIncrement 81 | 82 | 挑一个来分析,该API在kernel32.dll中 83 | 84 | ```asm 85 | .text:7C809806 ; LONG __stdcall InterlockedIncrement(volatile LONG *lpAddend) 86 | .text:7C809806 public InterlockedIncrement 87 | .text:7C809806 InterlockedIncrement proc near ; CODE XREF: CreatePipe+57↓p 88 | .text:7C809806 ; sub_7C82CBB2+41↓p ... 89 | .text:7C809806 90 | .text:7C809806 lpAddend = dword ptr 4 91 | .text:7C809806 92 | .text:7C809806 mov ecx, [esp+lpAddend] 93 | .text:7C80980A mov eax, 1 ; 将需要修改的变量的地址赋给ecx,此时可以通过[ecx]访问该变量的值 94 | .text:7C80980F 95 | .text:7C80980F loc_7C80980F: ; DATA XREF: .data:off_7C88500C↓o 96 | .text:7C80980F lock xadd [ecx], eax ; 第一部分是lock,用来锁住内存;另一部分核心在于xadd指令,该指令接收2个参数,先交换两个操作数的值,再进行算术加法操作: 97 | .text:7C80980F ; DWORD temp; 98 | .text:7C80980F ; temp = [ecx]; 99 | .text:7C80980F ; [ecx] = eax; 100 | .text:7C80980F ; eax = temp; 101 | .text:7C80980F ; [ecx] += eax; 102 | .text:7C809813 inc eax ; eax自增1,此时eax和[ecx]的值相同,eax可以起到返回值的作用(尽管已经完成对[ecx]值的修改) 103 | .text:7C809814 retn 4 104 | .text:7C809814 InterlockedIncrement endp 105 | ``` 106 | 107 | 108 | 109 | ## 多行指令的同步 110 | 111 | ### 临界区 112 | 113 | 可以设置一个临界区:一次只允许一个线程进入直到离开,从而保证线程的同步(这里的临界区指的是广义的临界区,各个操作系统根据临界区的思想都有各自的实现,后面也会学习到Windows提供的临界区实现)参考如下代码: 114 | 115 | ```c 116 | DWORD dwFlag = 0; //实现临界区的方式就是加锁 117 | //锁:全局变量 进去加一 出去减一 118 | if(dwFlag == 0) //进入临界区 119 | { 120 | dwFlag = 1 121 | ....... 122 | ....... 123 | ....... 124 | 125 | dwFlag = 0 //离开临界区 126 | } 127 | ``` 128 | 129 | 仔细观察一遍这个代码,其实是有问题的,考虑一种情况,在进入临界区后,如果dwFlag = 1这条指令还没有执行,此时发生了线程切换,这时,切换后的新线程也可以进入临界区,这样临界区的作用就失效了。 130 | 131 | ### 自己实现临界区 132 | 133 | ```asm 134 | //定义全局变量 135 | Flag = 0; 136 | 137 | //进入临界区 138 | Lab: 139 | mov eax,1 140 | //多核情况下必须加lock 141 | lock xadd [Flag],eax 142 | cmp eax,0 143 | jz endLab 144 | dec [Flag] 145 | //线程等待Sleep.. 146 | jmp Lab 147 | 148 | //临界区内部 149 | endLab: 150 | ret 151 | 152 | //离开临界区 153 | lock dec [Flag] 154 | ``` 155 | 156 | 这份伪代码提供了一个新的思路,在进入临界区之前,先判断锁的值,若达到进入临界区的条件,则**先修改锁的值**,**再进入临界区**;**若条件不符合**,则调用sleep()函数,进行**线程等待**。一段时间后,在跳回进入临界区的地方重新判断。在**线程退出临界区**后,**再**通过原子操作**还原锁的值**。 157 | 158 | 159 | 160 | 161 | 162 | # 02.自旋锁 163 | 164 | > [多核同步之自旋锁](https://cataloc.gitee.io/blog/2020/05/09/%E5%A4%9A%E6%A0%B8%E5%90%8C%E6%AD%A5%E4%B9%8B%E8%87%AA%E6%97%8B%E9%94%81/) 165 | > 166 | > [自旋锁 , cmpxchg8b 指令](https://blog.csdn.net/Kwansy/article/details/109995196) 167 | > 168 | > [多核同步&内核重载](https://blog.csdn.net/qq_41988448/article/details/103585673) 169 | > 170 | > [读书笔记之《Windows内核原理与实现》](https://blog.csdn.net/whatday/article/details/13170495) 171 | 172 | Windows提供的一种实现多核同步的机制:**自旋锁**。 173 | 174 | ``` 175 | //单核 176 | ntkrnlpa.exe 2-9-9-12分页 177 | ntoskrnl.exe 10-10-12分页 178 | 179 | //多核: 180 | ntkrnlpa.exe(ntkrpamp.exe) 2-9-9-12分页 181 | ntoskrnl.exe(ntkrnlmp.exe) 10-10-12分页 182 | ``` 183 | 184 | Intel的CPU,**多核情况下**,**系统安装时将ntkrnlmp.exe拷贝为ntoskrnl.exe**,系统加载时加载这个(原来是ntkrnlmp.exe的)ntoskrnl.exe。所以Intel多核情况下,内核**文件名仍然是ntoskrnl.exe**,但是其**源文件名是ntkrnlmp.exe**,如果加载符号,符号文件名也是ntkrnlmp.pdb。也因此,单核,多核情况下都叫做ntoskrnl.exe。 185 | 186 | 注意设置虚拟机CPU核心数量, 187 | 188 | > 用一个例子来解释临界区和自旋锁的区别。只有一个厕所,有一个人进去了。 189 | > 190 | > 临界区就是外面的人过来看一眼发现没位子,就回家睡觉了,睡醒了再回来看看有没有位子,重复这样的步骤; 191 | > 192 | > 自旋锁就是外面人一看没位置,他就在原地打转,一有位子马上就进去了。 193 | > 194 | 195 | ## KeAcquireSpinLockAtDpcLevel 196 | 197 | > [BT、BTS、BTR、BTC: 位测试指令](https://www.cnblogs.com/del/archive/2010/04/15/1712467.html) 198 | 199 | 首先介绍两个指令,一个是bt一个是bts: 200 | 201 | 202 | - BT(Bit Test):位测试 203 | 204 | ```asm 205 | ;BT 把 10000001b 的第七位复制到 CF, 得知是 1 206 | mov dx, 10000001b 207 | bt dx, 7 208 | ``` 209 | 210 | 211 | - BTS(Bit Test and Set:位测试并置位 212 | 213 | ```asm 214 | ;BTS 在执行 BT 命令的同时, 把操作数的指定位置为 1 215 | mov dx, 10000001b 216 | bts dx, 6 217 | ``` 218 | 219 | 220 | 单核的是直接retn了。 221 | 222 | 多核: 223 | 224 | ```asm 225 | text:0040B38B ; __stdcall KeAcquireSpinLockAtDpcLevel(x) 226 | .text:0040B38B public _KeAcquireSpinLockAtDpcLevel@4 227 | .text:0040B38B _KeAcquireSpinLockAtDpcLevel@4 proc near 228 | .text:0040B38B 229 | .text:0040B38B arg_0 = dword ptr 4 230 | .text:0040B38B 231 | .text:0040B38B mov ecx, [esp+arg_0] 232 | .text:0040B38F 233 | .text:0040B38F loc_40B38F: ; CODE XREF: KeAcquireSpinLockAtDpcLevel(x)+14↓j 234 | .text:0040B38F lock bts dword ptr [ecx], 0 ; 235 | .text:0040B38F ; 1.先判断[ecx]是否为0,是的话CF=1,否则为0 236 | .text:0040B38F ; 2.将[ecx]指定的下标置1 237 | .text:0040B38F ; 加lock保证多核情况下的安全 238 | .text:0040B394 jb short loc_40B399 ; 239 | .text:0040B394 ; 如果[ecx]!=0则跳转 240 | .text:0040B394 ; 如果[ecx]==0说明没有线程进入当前临界区 241 | .text:0040B396 retn 4 242 | .text:0040B399 ; --------------------------------------------------------------------------- 243 | .text:0040B399 244 | .text:0040B399 loc_40B399: ; CODE XREF: KeAcquireSpinLockAtDpcLevel(x)+9↑j 245 | .text:0040B399 ; KeAcquireSpinLockAtDpcLevel(x)+18↓j 246 | .text:0040B399 test dword ptr [ecx], 1 ; 如果[ecx]!=1则跳转 247 | .text:0040B399 ; 如果[ecx]==1说明当前资源被占用 248 | .text:0040B39F jz short loc_40B38F ; 跳到开头再来KeAcquireSpinLockAtDpcLevel 249 | .text:0040B3A1 pause ; CPU降温指令,短时间内降低CPU功率 250 | .text:0040B3A3 jmp short loc_40B399 ; 重复执行这几行指令,故称为自旋锁 251 | .text:0040B3A3 _KeAcquireSpinLockAtDpcLevel@4 endp 252 | ``` 253 | 254 | ## 思考题 255 | 256 | - 如何HOOK高并发的内核函数? 257 | 258 | > 这个问题的关键是,hook 后一般是 e8 / e9 后跟4字节,总共5字节,但没办法一次性改5个字节,可能改了第一个字节,正要改后4个字节时,别的线程进来了,就会出错。 259 | > 260 | > 有三种办法: 261 | > 262 | > - 短跳中转 263 | > - 中断门 264 | > - 找一条一次性修改8字节的指令 265 | 266 | 1. 先在附近未使用的内存空间构造一个**长跳转**(五个字节),再在要hook的地方构造一个**短跳转**(一次性写入两个字节)指向长跳转位置 267 | 2. 使用 **cmpxchg8b** 指令最多可一次性写入**八个字节** 268 | 269 | ------------------ 270 | 271 | **cmpxchg8b**指令 272 | 273 | > cmpxchg8b mem64 指令的工作如下: 274 | > 比较 mem64 和 EDX:EAX 275 | > 如果相等,那么把 ECX:EBX 存储到 mem64 276 | > 如果不相等,那么把 mem64 存储到 EDX:EAX 277 | 278 | # 03.线程等待与唤醒 279 | 280 | 上两节中无论是自己实现的临界区还是win自旋锁都会让当前线程进入等待状态,一个是sleep实现,一个是让当前的CPU”空转”(pause)实现,但都有局限性: 281 | 282 | 1. sleep:时间如何确定? 283 | 2. pause:只有等待时间很短的情况下才有意义,否则对CPU资源是种浪费。而且自旋锁只能在多核的环境下才有意义 284 | 285 | ## 等待与唤醒机制 286 | 287 | 在Windows中,一个线程可以通过等待一个或者多个可等待对象,从而进入等待状态,另一个线程可以在某些时刻唤醒等待这些对象的其他线程 288 | 289 | ![](./06事件等待/image-20230220171234183.png) 290 | 291 | ### 可等待对象 292 | 293 | 结构体中包含`_DISPATCHER_HEADER`,都为可等待对象 294 | 295 | ``` 296 | dt _KPROCESS 进程 297 | dt _KTHREAD 线程 298 | dt _KTIMER 定时器 299 | dt _KSEMAPHORE 信号量 300 | dt _KEVENT 事件 301 | dt _KMUTANT 互斥体 302 | dt _FILE_OBJECT 文件 303 | ``` 304 | 305 | ### 可等待对象的差异 306 | 307 | 其差异如下,在NtWaitForSingleObject如果不是可等待对象,其会插入一个_DISPATCH_HEADER结构体,使其变为可等待对象。 308 | 309 | ```c 310 | WaitForSingleObject(3环) -> 311 | 312 | NtWaitForSingleObject(内核)-> 313 | 通过3环用户提供的句柄,找到等待对象的内核地址。 314 | 如果是以 _DISPATCHER_HEADER 开头,直接使用。 315 | 如果不是以 _DISPATCHER_HEADER 开头的对象,则找到在其中嵌入的 _DISPATCHER_HEADER 对象 316 | 317 | KeWaitForSingleObject(内核) //核心功能 318 | ``` 319 | 320 | 321 | 322 | ## 等待网 323 | 324 | 先介绍简单的 325 | 326 | ### 一个线程等待一个内核对象 327 | 328 | > 这里会讲等待块的内容, 329 | 330 | 示例代码: 331 | 332 | ```c 333 | #include 334 | #include 335 | 336 | HANDLE hEvent[2]; 337 | 338 | DWORD WINAPI ThreadProc(LPVOID lpParamter) 339 | { 340 | ::WaitForSingleObject(hEvent[0], -1); 341 | 342 | printf("ThreadProc函数执行\n"); 343 | return 0; 344 | } 345 | 346 | 347 | int main(int argc, char* argv[]) 348 | { 349 | hEvent[0] = ::CreateEvent(NULL, TRUE, FALSE, NULL); //创建一个可等待对象 _KEVENT 350 | 351 | ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc, NULL, 0, NULL); 352 | 353 | getchar(); 354 | return 0; 355 | } 356 | ``` 357 | 358 | windbg中找到该进程,查看该进程: 359 | 360 | ``` 361 | kd> !process 8630a020 362 | Failed to get VadRoot 363 | PROCESS 8630a020 SessionId: 0 Cid: 01f4 Peb: 7ffd5000 ParentCid: 0790 364 | DirBase: 06bc0260 ObjectTable: e25bd1f0 HandleCount: 12. 365 | Image: test.exe 366 | VadRoot 00000000 Vads 0 Clone 0 Private 36. Modified 0. Locked 0. 367 | DeviceMap e1b1c3f8 368 | Token e108ed48 369 | ElapsedTime 00:00:08.156 370 | UserTime 00:00:00.015 371 | KernelTime 00:00:00.000 372 | QuotaPoolUsage[PagedPool] 0 373 | QuotaPoolUsage[NonPagedPool] 0 374 | Working Set Sizes (now,min,max) (177, 50, 345) (708KB, 200KB, 1380KB) 375 | PeakWorkingSetSize 177 376 | VirtualSize 7 Mb 377 | PeakVirtualSize 7 Mb 378 | PageFaultCount 170 379 | MemoryPriority FOREGROUND 380 | BasePriority 8 381 | CommitCharge 47 382 | 383 | THREAD 864608b8 Cid 01f4.01ec Teb: 7ffdf000 Win32Thread: 00000000 WAIT: (WrLpcReply) UserMode Non-Alertable 384 | 86460aac Semaphore Limit 0x1 385 | Waiting for reply to LPC MessageId 00008497: 386 | Current LPC port e14fa8b8 387 | Not impersonating 388 | DeviceMap e1b1c3f8 389 | Owning Process 00000000 Image: 390 | Attached Process 8630a020 Image: test.exe 391 | Wait Start TickCount 30765 Ticks: 520 (0:00:00:08.125) 392 | Context Switch Count 19 IdealProcessor: 0 393 | UserTime 00:00:00.000 394 | KernelTime 00:00:00.000 395 | Win32 Start Address 0x00401570 396 | Stack Init ee42f000 Current ee42ec50 Base ee42f000 Limit ee42c000 Call 00000000 397 | Priority 10 BasePriority 8 PriorityDecrement 2 IoPriority 0 PagePriority 0 398 | ChildEBP RetAddr 399 | ee42ec68 8050493e nt!KiSwapContext+0x2f (FPO: [Uses EBP] [0,0,4]) 400 | ee42ec74 804fc0d8 nt!KiSwapThread+0x8a (FPO: [0,0,0]) 401 | ee42ec9c 805a43e7 nt!KeWaitForSingleObject+0x1c2 (FPO: [Non-Fpo]) 402 | ee42ed50 805427e8 nt!NtRequestWaitReplyPort+0x63d (FPO: [Non-Fpo]) 403 | 404 | ee42ed50 7c92e4f4 (T) nt!KiSystemServicePostCall (FPO: [0,0] TrapFrame @ ee42ed64) 405 | WARNING: Frame IP not in any known module. Following frames may be wrong. 406 | 407 | 0012fce4 00000000 (T) 0x7c92e4f4 408 | 409 | THREAD 86101020 Cid 01f4.03b8 Teb: 7ffde000 Win32Thread: 00000000 WAIT: (UserRequest) UserMode Non-Alertable 410 | 85fd1468 NotificationEvent 411 | Not impersonating 412 | DeviceMap e1b1c3f8 413 | Owning Process 00000000 Image: 414 | Attached Process 8630a020 Image: test.exe 415 | Wait Start TickCount 30765 Ticks: 520 (0:00:00:08.125) 416 | Context Switch Count 2 IdealProcessor: 0 417 | UserTime 00:00:00.000 418 | KernelTime 00:00:00.000 419 | Win32 Start Address 0x00401005 420 | Stack Init ee657000 Current ee656ca0 Base ee657000 Limit ee654000 Call 00000000 421 | Priority 8 BasePriority 8 PriorityDecrement 0 IoPriority 0 PagePriority 0 422 | ChildEBP RetAddr 423 | ee656cb8 8050493e nt!KiSwapContext+0x2f (FPO: [Uses EBP] [0,0,4]) 424 | ee656cc4 804fc0d8 nt!KiSwapThread+0x8a (FPO: [0,0,0]) 425 | ee656cec 805c17c8 nt!KeWaitForSingleObject+0x1c2 (FPO: [Non-Fpo]) 426 | ee656d50 805427e8 nt!NtWaitForSingleObject+0x9a (FPO: [Non-Fpo]) 427 | 428 | ee656d50 7c92e4f4 (T) nt!KiSystemServicePostCall (FPO: [0,0] TrapFrame @ ee656d64) 429 | WARNING: Frame IP not in any known module. Following frames may be wrong. 430 | 431 | 0052ff44 00000000 (T) 0x7c92e4f4 432 | ``` 433 | 434 | 一般来说,最后一个就是我们想要找的线程: 435 | 436 | ``` 437 | kd> dt _KTHREAD 86101020 438 | nt!_KTHREAD 439 | ... 440 | +0x05c WaitBlockList : 0x86101090 _KWAIT_BLOCK 441 | +0x060 WaitListEntry : _LIST_ENTRY [ 0x85fd7ad0 - 0x86460918 ] 442 | +0x060 SwapListEntry : _SINGLE_LIST_ENTRY 443 | ... 444 | ``` 445 | 446 | 这里重点关注0x5c的位置,是**等待块**: 447 | 448 | ``` 449 | kd> dt _KWAIT_BLOCK 0x86101090 450 | nt!_KWAIT_BLOCK 451 | +0x000 WaitListEntry : _LIST_ENTRY [ 0x85fd1470 - 0x85fd1470 ] 452 | +0x008 Thread : 0x86101020 _KTHREAD 453 | +0x00c Object : 0x85fd1468 Void 454 | +0x010 NextWaitBlock : 0x86101090 _KWAIT_BLOCK 455 | +0x014 WaitKey : 0 456 | +0x016 WaitType : 1 457 | ``` 458 | 459 | 这就是我们要找的等待块。由于线程只等待一个事件对象,所以只有一个可用的等待块,这里为什么说是可用的。因为虽然有4个等待块,最后一个也就是第四个等待块已经被占坑了,也就是我们调用`WaitForSingleObject`函数后的等待超时时间,如果是某一个值,第四个等待块就会启用,也就是计时器。第四个等待块: 460 | 461 | ``` 462 | kd> dt _KWAIT_BLOCK 0x86101090+18*3 463 | nt!_KWAIT_BLOCK 464 | +0x000 WaitListEntry : _LIST_ENTRY [ 0x86101118 - 0x86101118 ] 465 | +0x008 Thread : 0x86101020 _KTHREAD 466 | +0x00c Object : 0x86101110 Void 467 | +0x010 NextWaitBlock : (null) 468 | +0x014 WaitKey : 0x102 469 | +0x016 WaitType : 1 470 | ``` 471 | 472 | - `WaitKey`是指等待块的索引,但是对于第四个等待块,它是特殊的,被赋予了比较大的值`0x102` 473 | 474 | - `Thread`指向当前线程 475 | 476 | - `Object`指的是被等待的对象的地址 477 | 478 | - 看一下是不是事件: 479 | 480 | ```sh 481 | kd> dt _OBJECT_HEADER 0x85fd1468-18 482 | nt!_OBJECT_HEADER 483 | +0x000 PointerCount : 0n2 484 | +0x004 HandleCount : 0n1 485 | +0x004 NextToFree : 0x00000001 Void 486 | +0x008 Type : 0x865bb360 _OBJECT_TYPE 487 | +0x00c NameInfoOffset : 0 '' 488 | +0x00d HandleInfoOffset : 0 '' 489 | +0x00e QuotaInfoOffset : 0 '' 490 | +0x00f Flags : 0 '' 491 | +0x010 ObjectCreateInfo : 0x8633f860 _OBJECT_CREATE_INFORMATION 492 | +0x010 QuotaBlockCharged : 0x8633f860 Void 493 | +0x014 SecurityDescriptor : (null) 494 | +0x018 Body : _QUAD 495 | kd> dt _OBJECT_TYPE 0x865bb360 496 | nt!_OBJECT_TYPE 497 | +0x000 Mutex : _ERESOURCE 498 | +0x038 TypeList : _LIST_ENTRY [ 0x865bb398 - 0x865bb398 ] 499 | +0x040 Name : _UNICODE_STRING "Event" 500 | +0x048 DefaultObject : (null) 501 | +0x04c Index : 9 502 | +0x050 TotalNumberOfObjects : 0x4b7 503 | +0x054 TotalNumberOfHandles : 0x4ed 504 | +0x058 HighWaterNumberOfObjects : 0x4f2 505 | +0x05c HighWaterNumberOfHandles : 0x52b 506 | +0x060 TypeInfo : _OBJECT_TYPE_INITIALIZER 507 | +0x0ac Key : 0x6e657645 508 | +0x0b0 ObjectLocks : [4] _ERESOURCE 509 | ``` 510 | 511 | - `NextWaitBlock`指向的就是下一个等待块的地址 512 | 513 | - `WaitType`是等待类型 514 | 515 | - `WaitListEntry`这个成员,需要看一下被等待对象的`Head`成员 516 | 517 | ```sh 518 | kd> dt _KEVENT 0x85fd1468 519 | nt!_KEVENT 520 | +0x000 Header : _DISPATCHER_HEADER 521 | kd> dt _DISPATCHER_HEADER 0x85fd1468 522 | nt!_DISPATCHER_HEADER 523 | +0x000 Type : 0 '' 524 | +0x001 Absolute : 0xfc '' 525 | +0x002 Size : 0x4 '' 526 | +0x003 Inserted : 0x86 '' 527 | +0x004 SignalState : 0n0 528 | +0x008 WaitListHead : _LIST_ENTRY [ 0x86101090 - 0x86101090 ] 529 | kd> dt _LIST_ENTRY 0x85fd1468+8 530 | nt!_LIST_ENTRY 531 | [ 0x86101090 - 0x86101090 ] 532 | +0x000 Flink : 0x86101090 _LIST_ENTRY [ 0x85fd1470 - 0x85fd1470 ] 533 | +0x004 Blink : 0x86101090 _LIST_ENTRY [ 0x85fd1470 - 0x85fd1470 ] 534 | ``` 535 | 536 | 被等待对象的`Header`成员中的`WaitListHead`会把用来等待它的等待块通过`WaitListEntry`串起来,这个就是该成员的作用。 537 | 538 | ![img](./06事件等待/2520882-20220211162824199-327227111.png) 539 | 540 | ### 一个线程等待多个内核对象 541 | 542 | 这样的话,上面的图就变成了这样: 543 | 544 | ![img](./06事件等待/2520882-20220211162831246-1280864920.png) 545 | 546 | 示例代码: 547 | 548 | ```c 549 | #include 550 | #include 551 | 552 | HANDLE hEvent[2]; 553 | 554 | DWORD WINAPI ThreadProc(LPVOID lpParamter) 555 | { 556 | ::WaitForMultipleObjects(2, hEvent, FALSE, -1); 557 | 558 | printf("ThreadProc函数执行\n"); 559 | return 0; 560 | } 561 | 562 | 563 | int main(int argc, char* argv[]) 564 | { 565 | hEvent[0] = ::CreateEvent(NULL, TRUE, FALSE, NULL); //创建可等待对象 566 | hEvent[1] = ::CreateEvent(NULL, TRUE, FALSE, NULL); //创建可等待对象 567 | 568 | ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc, NULL, 0, NULL); 569 | 570 | getchar(); 571 | return 0; 572 | } 573 | 574 | ``` 575 | 576 | wingdb: 577 | 578 | ```sh 579 | kd> dt _KTHREAD 86149c68 580 | nt!_KTHREAD 581 | ... 582 | +0x05c WaitBlockList : 0x86149cd8 _KWAIT_BLOCK 583 | +0x060 WaitListEntry : _LIST_ENTRY [ 0x86042e00 - 0x86450910 ] 584 | ... 585 | kd> dt _KWAIT_BLOCK 0x86149cd8 586 | nt!_KWAIT_BLOCK 587 | +0x000 WaitListEntry : _LIST_ENTRY [ 0x86116e20 - 0x86116e20 ] 588 | +0x008 Thread : 0x86149c68 _KTHREAD 589 | +0x00c Object : 0x86116e18 Void 590 | +0x010 NextWaitBlock : 0x86149cf0 _KWAIT_BLOCK 591 | +0x014 WaitKey : 0 592 | +0x016 WaitType : 1 593 | kd> dt _KWAIT_BLOCK 0x86149cf0 594 | nt!_KWAIT_BLOCK 595 | +0x000 WaitListEntry : _LIST_ENTRY [ 0x85feeff8 - 0x85feeff8 ] 596 | +0x008 Thread : 0x86149c68 _KTHREAD 597 | +0x00c Object : 0x85feeff0 Void 598 | +0x010 NextWaitBlock : 0x86149cd8 _KWAIT_BLOCK 599 | +0x014 WaitKey : 1 600 | +0x016 WaitType : 1 601 | ``` 602 | 603 | ### 等待网 604 | 605 | 一个一个线程交错起来,有的被等待对象同时被多个线程等待,就会形成错综复杂的网络,也就是所谓的等待网: 606 | 607 | ![img](./06事件等待/2520882-20220211162838959-1627623022.png) 608 | 609 | ## 总结 610 | 611 | 1. 等待中的线程,一定在等待链表中(`KiWaitListHead`),同时也一定在这张网上(`KTHREAD +5C`的位置不为空) 612 | 2. 线程通过调用`WaitForSingleObject`/`WaitForMultipleObjects`函数将自己挂到这张网上 613 | 3. 线程什么时候会再次执行取决于其他线程何时调用相关函数,等待对象不同调用的函数也不同 614 | 615 | # 04.WaitForSingleObject函数分析 616 | 617 | 618 | 619 | ```c 620 | WaitForSingleObject-> 621 | WaitForSingleObjectEx-> 622 | 进入内核-> 623 | NtWaitForSingleObject-> 624 | KeWaitForSingleObject 625 | ``` 626 | 627 | ## NtWaitForSingleObject 628 | 629 | 函数原型: 630 | 631 | ```c 632 | NTSTATUS __stdcall NtWaitForSingleObject( 633 | HANDLE Handle, //用户层传递的等待对象的句柄 634 | BOOLEAN Alertable, //KTHREAD结构体的Alertable属性。如果为1,则在插入用户APC时,该线程将被唤醒。注意这里的唤醒只是唤醒该线程执行APC,而不是真正的唤醒。因为如果当前的线程在等待网上,执行完用户APC后,仍然要进入等待状态。 635 | PLARGE_INTEGER Timeout//Timeout就是超时时间,就算没等待到符合条件到了指定事件也会被唤醒。 636 | ) 637 | ``` 638 | 639 | 再说下`DISPATCHER_HEADER`这个结构: 640 | 641 | ```sh 642 | kd> dt _DISPATCHER_HEADER 643 | ntdll!_DISPATCHER_HEADER 644 | +0x000 Type : UChar 645 | +0x001 Absolute : UChar 646 | +0x002 Size : UChar 647 | +0x003 Inserted : UChar 648 | +0x004 SignalState : Int4B 649 | +0x008 WaitListHead : _LIST_ENTRY 650 | ``` 651 | 652 | `Type`是类型,每一个可以被等待的对象的类型是不一样的。具体值需要通过内核初始化代码可以逆向出。不同的类型,`WaitForSingleObject`处理方式是不一样的。`SignalState`指示有没有信号,如果有信号则值大于0。 653 | 654 | ### 实现 655 | 656 | 1) 调用`ObReferenceObjectByHandle`函数,通过对象句柄找到等待对象结构体地址。 657 | 2) 调用`KeWaitForSingleObject`函数,进入关键循环。 658 | 659 | ## KeWaitForSingleObject 660 | 661 | ### 上半部分 662 | 663 | 1. 准备等待块,当等待对象少于四个时,并不为等待对象分配新的空间,而是向 `_KTHREAD(+70)` 位置的等待块赋值,_KTHREAD(+5C) 指向第一个等待块的位置 664 | 665 | 注意:**无论使用与否,`_KTHREAD(+70)`的第四个等待块被定时器占据,如果用的话,将会把定时器与第一个等待块相关联** 666 | 667 | 2. 如果超时时间不为0,`_KTHREAD(+70)` 第四个等待块与第一个等待块关联起来: 668 | 669 | 第一个等待块指向第四个等待块,第四个等待块指向第一个等待块。 670 | 671 | 3. `_KTHREAD(+5C)` 指向第一个 `_KWAIT_BLOCK`。 672 | 673 | 4. 进入关键循环 674 | 675 | ### 关键循环 676 | 677 | 示例图: 678 | 679 | ![img](./06事件等待/2520882-20220211175941247-1806950584.png) 680 | 681 | 伪代码: 682 | 683 | ```c 684 | while(true)//每次线程被其他线程唤醒,都要进入这个循环 685 | { 686 | if(符合激活条件)//1、超时 2、等待对象SignalState>0 687 | { 688 | //1) 修改SignalState 689 | //2) 退出循环 690 | } 691 | else 692 | { 693 | if(第一次执行) 694 | 将当前线程的等待块挂到等待对象的链表(WaitListHead)中; 695 | 696 | //将自己挂入等待队列(KiWaitListHead),如果调用KeWaitForSingleObject这个函数,线程就会把自己挂到等待链表中 697 | //切换线程...再次获得CPU时,从这里开始执行 698 | } 699 | } 700 | //1) 线程将自己+5C位置清0 701 | //2) 释放 _KWAIT_BLOCK 所占内存 702 | ``` 703 | 704 | 流程: 705 | 706 | 1. 判断当前被等待对象是否有信号 707 | 2. (每一个线程与等待对象是通过等待块进行关联的,但是对象有一个条件:至少有一个成员为 `_DISPATCHER_HEADER` 结构体) 708 | 3. 第一次循环时,若等待对象有信号,但是未超时,就不会将当前线程的等待块挂到等待对象的链表(`WaitListHead`)中,直接修改信号的值,退出循环 709 | 4. 第一次循环时,若等待对象未超时,但是无信号,就将当前线程的等待块挂到等待对象的链表(`WaitListHead`)中,将线程自己挂入等待队列(`KiWaitListHead`),切换线程 710 | 5. 当线程将自己挂入等待队列后,需要等待另一个线程将自己唤醒(设置等待对象信号量>0),当其它线程将自己唤醒后,再沿着等待网找是谁唤醒了自己,找到了之后将自己从等待链表(`KiWaitListHead`)中摘出,但并未从等待网中摘出 711 | 6. 线程从哪里切换就从哪里复活 712 | 713 | ## 总结 714 | 715 | 1. 不同的等待对象,用不同的方法来修改 `_DISPATCHER_HEADER->SignalState` 716 | 717 | 2. 如果可等待对象是EVENT,其他线程通常使用SetEvent来设置SignalState = 1,并且,将正在等待该对象的其他线程唤醒,也就是从等待链表(`KiWaitListHead`)中摘出来,此时线程临时复活 718 | 719 | 3. SetEvent函数并不会将线程从等待网上摘下来,是否要下来,由当前线程自己来决定 720 | 721 | 4. 若使用SetEvent这种函数直接将线程从等待网上摘下来,将会非常麻烦,因为可能有非常多的线程在等待一个对象,无法判断该将谁摘下(一个也线程可能等待着多个对象) 722 | 723 | 比如:线程A和线程B同时在等待着一个对象,这时如果有线程C调用了SetEvent(将等待对象的信号量置1),线程A和线程B会被临时唤醒(从`KiWaitLkistHead`摘下),并行进入关键循环,假设线程A先运行,线程A会设置等待对象的信号量<=0,然后将自己从等待网上摘下来,此时线程A彻底复活。线程B再去判断等待对象是否有信号量时,已经没有信号量了,这时线程B会将自己重新挂入等待链表中 724 | 725 | 5. 不同对象调用API修改信号个数只在细节上有差异,本质上都是一样的 726 | 727 | 728 | 729 | # 05.事件 730 | 731 | ## 回顾 732 | 733 | 1. 线程在进入临界区之前会调用`WaitForSingleObject`或者`WaitForMultipleObjects` 734 | 2. 此时如果有信号,线程会从函数中退出并进入临界区;如果没有信号那么线程将自己挂入等待链表,然后将自己挂入等待网,最后切换线程 735 | 3. 其它线程在适当的时候,调用方法修改被等待对象的`SingleState`,设置为有信号(不同的等待对象,会调用不同的函数),并将等待该对象的其它线程从等待链表中摘掉,这样,当前线程便会在`WaitForSingleObject`或者`WaitForMultipleObjects`恢复执行(在哪切换就在哪开始执行),如果符合唤醒条件,此时会修改`SignalState`的值,并将自己从等待网上摘下来,此时的线程才是真正的唤醒 736 | 4. 被等待对象不同,主要差异在以下两点: 737 | 1. 不同的被等待对象,修改`SingnalState`所调用的函数不同 738 | 2. 当前线程一旦被临时唤醒后,会从原来进入等待状态的地方继续执行,不同的等待对象,判断是否符合激活条件和修改`SignalState`的具体操作不同 739 | 740 | 741 | 742 | 743 | 744 | ## CreateEvent参数介绍 745 | 746 | SetEvent对应的内核函数:`KeSetEvent` 747 | 748 | 1) 修改信号值`SignalState`为1 749 | 750 | 2) 判断对象类型 751 | 752 | 3) 如果类型为通知类型对象(0) 唤醒所有等待该状态的线程 753 | 754 | 4) 如果类型为事件同步对象(1) 从链表头找到第一个 755 | 756 | 757 | 758 | 759 | 760 | 事件的内核结构体: 761 | 762 | ``` 763 | kd> dt _KEVENT 764 | ntdll!_KEVENT 765 | +0x000 Header : _DISPATCHER_HEADER 766 | ``` 767 | 768 | 就一个必须的`_DISPATCHER_HEADER`,通常用`CreateEvent`函数来进行创建使用这个内核对象,函数原型: 769 | 770 | ```c 771 | HANDLE WINAPI CreateEventW( 772 | LPSECURITY_ATTRIBUTES lpEventAttributes, 773 | BOOL bManualReset,//布尔型,如果为True,则为通知类型对象;反之则为普通的事件同步对象。这个参数影响_DISPATCHER_HEADER的Type值,如果为通知类型对象,它的值为0,否则为1 774 | BOOL bInitialState, 775 | LPCWSTR lpName 776 | ); 777 | ``` 778 | 779 | ### bManualReset 780 | 781 | 1. 当**CreateEvent**第二个参数为**TRUE**,系统将事件对象的**Type**设置成**0**,此时对象为通知类型类型 782 | 2. 当**CreateEvent**第二个参数为**FALSE**,系统将事件对象的**Type**设置成**1**,此时对象为事件同步对象 783 | 3. 当SetEvent函数将信号值(**SignalState**)设置为1时,如果对象**Type**为**0**,唤醒所有等待该状态的线程;如果对象**Type**为**1**,从链表头找到第一个并唤醒 784 | 785 | ``` 786 | kd> dt _DISPATCHER_HEADER 787 | ntdll!_DISPATCHER_HEADER 788 | +0x000 Type : UChar 789 | +0x001 Absolute : UChar 790 | +0x002 Size : UChar 791 | +0x003 Inserted : UChar 792 | +0x004 SignalState : Int4B 793 | +0x008 WaitListHead : _LIST_ENTRY 794 | ``` 795 | 796 | 示例代码: 797 | 798 | ```c 799 | #include 800 | #include 801 | #include 802 | HANDLE hEvent; 803 | 804 | DWORD WINAPI ThreadProc1(LPVOID param) 805 | { 806 | WaitForSingleObject(hEvent,INFINITE); 807 | puts("等待线程1执行!"); 808 | return 0; 809 | } 810 | 811 | DWORD WINAPI ThreadProc2(LPVOID param) 812 | { 813 | WaitForSingleObject(hEvent,INFINITE); 814 | puts("等待线程2执行!"); 815 | return 0; 816 | } 817 | 818 | int main(int argc, char* argv[]) 819 | { 820 | hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); 821 | CloseHandle(CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)ThreadProc1,NULL,NULL,NULL)); 822 | CloseHandle(CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)ThreadProc2,NULL,NULL,NULL)); 823 | SetEvent(hEvent); 824 | system("pause"); 825 | CloseHandle(hEvent); 826 | return 0; 827 | } 828 | ``` 829 | 830 | 可以看到当第二个参数是True,也就是通知类型对象的时候,两个线程都执行了: 831 | 832 | ![image-20230221104041091](./06事件等待/image-20230221104041091.png) 833 | 834 | 将第二个参数改为False,也就是同步类型对象的时候,只有线程1执行了: 835 | 836 | ![image-20230221104359682](./06事件等待/image-20230221104359682.png) 837 | 838 | ### bInitialState 839 | 840 | 是否有信号。这个参数设置`_DISPATCHER_HEADER`的`SignalState`初始值的,`TRUE`就是1,反之就是0。将上面的原始代码的第三个参数改为`TRUE`,并注释掉`SetEvent`函数: 841 | 842 | ![image-20230221104635043](./06事件等待/image-20230221104635043.png) 843 | 844 | ## KeWaitForSingleObject 845 | 846 | ![image-20230221111107246](./06事件等待/image-20230221111107246.png) 847 | 848 | # 06.信号量 849 | 850 | 851 | 852 | ## 回顾 853 | 854 | 线程在进入临界区之前会通过调用`WaitForSingleObject`或者`WaitForMultipleObjects`来判断当前的事件对象是否有信号(SignalState>0),只有当事件对象有信号时,才可以进入临界区(只允许一个线程进入直到退出的一段代码,不单指用`EnterCriticalSection`() 和 `LeaveCriticalSection`() 而形成的临界区)。 855 | 856 | 通过我们对EVENT对象相关函数的分析,我们发现,EVENT对象的SignalState值只有2种可能: 857 | 858 | 1:初始化时 或者调用 `SetEvent` 859 | 0:`WaitForSingleObject`、`WaitForMultipleObjects`、`ResetEvent` 860 | 861 | 862 | 863 | ## 信号量 864 | 865 | **描述**: 866 | 867 | 1. 在**事件**中,当一个线程进入临界区时,其它所有事件都无法进入临界区 868 | 2. **信号量**允许多个线程进入临界区 869 | 870 | **优点**:举个例子,在生产者与消费者的问题中,若生产者只有三份,那么开五个消费者线程是没有意义的,信号量的存在正是为了解决这种问题 871 | 872 | ## CreateSemaphore 873 | 874 | 信号量内核结构体: 875 | 876 | ``` 877 | kd> dt _KSEMAPHORE 878 | ntdll!_KSEMAPHORE 879 | +0x000 Header : _DISPATCHER_HEADER 880 | +0x010 Limit : Int4B 881 | ``` 882 | 883 | 函数原型 884 | 885 | ```c 886 | HANDLE WINAPI CreateSemaphoreW( 887 | LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, 888 | LONG lInitialCount,//这个参数会影响_DISPATCHER_HEADER的SignalState的值。它不会像事件只设置0或者1,它可以设置更大的数,这个就是实现指定数目线程执行的关键所在。 889 | LONG lMaximumCount,//信号量内核结构体的Limit部分 890 | LPCWSTR lpName 891 | ); 892 | ``` 893 | 894 | ### 调用流程 895 | 896 | ```c 897 | ReleaseSemaphore -> 898 | NtReleaseSemaphore -> 899 | KeReleaseSemaphore 900 | ``` 901 | 902 | 1) 设置SignalState = SignalState + N(参数) 903 | 2) 通过`WaitListHead`找到所有线程,并从等待链表中摘掉(不从等待网上摘除,说了好多遍了)。 904 | 905 | 906 | 907 | # 07.互斥体 908 | 909 | ## 为什么有互斥体 910 | 911 | 互斥体(MUTANT)与事件(EVENT)和信号量(SEMAPHORE)一样,都可以用来进行线程的同步控制几个对象都是内核对象,这就意味着,通过这些对象可以进行跨进程的线程同步控制,比如: 912 | 913 | ``` 914 | A进程中的X线程 915 | 等待对象Z 916 | B进程中的Y线程 917 | ``` 918 | 919 | 假设有A进程中的X线程和B进程中的Y线程,它们都在等待内核对象Z。如果B进程的Y线程还没有来得及调用修改`SignalState`的函数,那么等待对象Z将被遗弃,这也就意味着X线程将永远等下去,这种情况下事件和信号量无法解决,互斥体可以解决。 920 | 921 | 还有一点:重入,或者说死锁 922 | 923 | 当构造了一个临界区一,等待的对象是A,又在临界区内部构造了一个临界区二,等待对象为A、B、C三个,当临界区一执行完自己的功能后,如果等待的对象为事件或者信号量,那么就必须调用相关API将对象设置为有信号,若进入临界区二前未调用相关API,那么临界区二将永远进入等待状态,这种情况称为死锁。 924 | 当一个对象需要重复进入临界区时,若A对象为互斥体,就不会出现死锁。 925 | 926 | ## 互斥体 927 | 928 | 互斥体内核结构: 929 | 930 | ```c 931 | kd> dt _KMUTANT 932 | nt!_KMUTANT 933 | +0x000 Header : _DISPATCHER_HEADER 934 | +0x010 MutantListEntry : _LIST_ENTRY//拥有互斥体线程 (KTHREAD+0x010 MutantListHead),是个链表头,圈着当前线程所有的互斥体 935 | +0x018 OwnerThread : Ptr32 _KTHREAD//正在拥有互斥体的线程 936 | +0x01c Abandoned : UChar//是否已经被放弃不用 937 | +0x01d ApcDisable : UChar//是否禁用内核APC 938 | 939 | ``` 940 | 941 | ### 创建互斥体 942 | 943 | `CreateMutex`函数原型: 944 | 945 | ```c 946 | HANDLE CreateMutex( 947 | LPSECURITY_ATTRIBUTE SlpMutexAttributes, // 指向安全属性的指针 948 | BOOL bInitialOwner, // 初始化互斥对象的所有者(是否是该线程) 949 | LPCTSTR lpName // 指向互斥对象名的指针 950 | ); 951 | ``` 952 | 953 | 调用过程: 954 | 955 | > `CreateMutex` -> `NtCreateMutant`(内核函数) -> `KeInitializeMutant`(内核函数) 956 | 957 | 初始化MUTANT结构体: 958 | 959 | ```c 960 | MUTANT.Header.Type=2; 961 | MUTANT.Header.SignalState=bInitialOwner ? 0 : 1; 962 | MUTANT.OwnerThread=bInitialOwner ? 当前线程 : NULL; 963 | MUTANT.Abandoned=0; 964 | MUTANT.ApcDisable=0; 965 | 966 | bInitialOwner==TRUE 将当前互斥体挂入到当前线程的互斥体链表 967 | (KTHREAD+0x010 MutantListHead) 968 | ``` 969 | 970 | ### KeWaitForMutexObject 971 | 972 | 973 | 974 | ```asm 975 | .text:004054D2 loc_4054D2: ; CODE XREF: KeWaitForSingleObject(x,x,x,x,x)+3C1C8↓j 976 | .text:004054D2 cmp byte ptr [ebx+_DISPATCHER_HEADER.Type], 2 ; 判断等待的对象类型是否是互斥体 977 | .text:004054D5 jnz loc_40265F ; 不是则跳转 978 | .text:004054DB mov eax, [ebx+_DISPATCHER_HEADER.SignalState] 979 | .text:004054DE test eax, eax ; 判断信号量是否为0 980 | .text:004054E0 jg loc_40261E 981 | .text:004054E6 cmp esi, [ebx+18h] ; nt!_KMUTANT 982 | .text:004054E6 ; +0x000 Header : _DISPATCHER_HEADER 983 | .text:004054E6 ; +0x010 MutantListEntry : _LIST_ENTRY 984 | .text:004054E6 ; +0x018 OwnerThread : Ptr32 _KTHREAD 985 | .text:004054E6 ; +0x01c Abandoned : UChar 986 | .text:004054E6 ; +0x01d ApcDisable : UChar 987 | .text:004054E9 jz loc_40261E ; 判断当前线程是否拥有该互斥体 988 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 989 | .text:0040261E loc_40261E: ; CODE XREF: KeWaitForSingleObject(x,x,x,x,x)+E0↓j 990 | .text:0040261E ; KeWaitForSingleObject(x,x,x,x,x)+E9↓j 991 | .text:0040261E cmp eax, 80000000h ; 最多进入次数0x80000000 992 | .text:00402623 jz loc_44AB42 993 | .text:00402629 dec dword ptr [ebx+_DISPATCHER_HEADER.SignalState] ; 不管什么原因进来的,都会执行这条指令 994 | .text:00402629 ; 当SignalState为0是,再次执行得0xFFFFFFFF 995 | .text:0040262C jnz short loc_402657 ; 唤醒原因 996 | .text:0040262E movzx eax, byte ptr [ebx+1Dh] ; nt!_KMUTANT 997 | .text:0040262E ; +0x000 Header : _DISPATCHER_HEADER 998 | .text:0040262E ; +0x010 MutantListEntry : _LIST_ENTRY 999 | .text:0040262E ; +0x018 OwnerThread : Ptr32 _KTHREAD 1000 | .text:0040262E ; +0x01c Abandoned : UChar 1001 | .text:0040262E ; +0x01d ApcDisable : UChar 1002 | .text:00402632 sub [esi+_KTHREAD.KernelApcDisable], eax ; 是否禁用内核APC 1003 | .text:00402638 cmp byte ptr [ebx+1Ch], 1 ; 判断是否被放弃使用 1004 | .text:0040263C mov [ebx+18h], esi ; 设置互斥所属线程 1005 | .text:0040263F jz loc_442A97 ; 被弃用,跳转 1006 | .text:00402645 1007 | .text:00402645 loc_402645: ; CODE XREF: KeWaitForSingleObject(x,x,x,x,x)+3D6A2↓j 1008 | .text:00402645 mov ecx, [esi+_KTHREAD.MutantListHead.Blink] ; 将互斥体加入到线程的MutantListHead链表中 1009 | .text:00402648 mov edx, [ecx] 1010 | .text:0040264A lea eax, [ebx+10h] ; 挂载到互斥体对象+10的位置 1011 | .text:0040264D mov [eax], edx ; 这几行是挂载链表的操作 1012 | .text:0040264F mov [eax+4], ecx 1013 | .text:00402652 mov [edx+4], eax 1014 | .text:00402655 mov [ecx], eax 1015 | ``` 1016 | 1017 | 1018 | 1019 | ### 释放互斥体 1020 | 1021 | 函数原型: 1022 | 1023 | ```c 1024 | BOOL WINAPI ReleaseMutex(HANDLE hMutex); 1025 | ``` 1026 | 1027 | 调用过程: 1028 | 1029 | > `ReleaseMutex` -> `NtReleaseMutant` -> `KeReleaseMutant` 1030 | 1031 | **正常调用时**: 1032 | 1033 | > MUTANT.Header.SignalState++; 1034 | 1035 | 如果SignalState=1(即退出最外圈临界区后),说明其他进程可以使用了,将该互斥体从线程链表中移除 1036 | 1037 | ### 解决遗弃问题 1038 | 1039 | **描述**: 1040 | 1041 | 当一个进程非正常“死亡时”,系统会调用内核函数`MmUnloadSystemImage`处理后事 1042 | 内核函数`MmUnloadSystemImage`会调用`KeReleaseMutant(X, Y, Abandon, Z)`,第三个参数用来判断该互斥体是否被丢弃,正常释放时值为false,有且只有互斥体有这个待遇 1043 | 1044 | **KeReleaseMutant函数判断:** 1045 | 1046 | 伪代码: 1047 | 1048 | ```c 1049 | if ( Abandoned ) 1050 | { 1051 | //将其置为符合其他线程激活条件的状态 1052 | Mutant->Header.SignalState = 1; 1053 | Mutant->Abandoned = 1; 1054 | } 1055 | else//正常调用,Abandon == false 1056 | { 1057 | ..... 1058 | ++Mutant->Header.SignalState; 1059 | } 1060 | if ( Mutant->Header.SignalState == 1 )//意外结束 1061 | { 1062 | 1063 | Mutant->OwnerThread = 0; 1064 | //从当前线程互斥体链表中将当前互斥体移除 1065 | ... 1066 | 1067 | } 1068 | ``` 1069 | 1070 | ### ApcDisable 1071 | 1072 | 1. **用户层**:**Mutant** 1073 | 对应内核函数:`NtCreateMutant` 1074 | ApcDisable=0 1075 | 2. **内核层**:**Mutex** 1076 | 对应内核函数:`NtCreateMutex` 1077 | ApcDisable=1 1078 | 1079 | 若在**三环**创建互斥体(Mutant),内核APC仍然可以使用;若通过**零环**创建互斥体(Mutex),那么当前内核APC是被禁止的 1080 | 1081 | ```asm 1082 | .text:0040261E loc_40261E: ; CODE XREF: KeWaitForSingleObject(x,x,x,x,x)+E0↓j 1083 | .text:0040261E ; KeWaitForSingleObject(x,x,x,x,x)+E9↓j 1084 | .text:0040261E cmp eax, 80000000h ; 最多进入次数0x80000000 1085 | .text:00402623 jz loc_44AB42 1086 | .text:00402629 dec dword ptr [ebx+_DISPATCHER_HEADER.SignalState] ; 不管什么原因进来的,都会执行这条指令 1087 | .text:00402629 ; 当SignalState为0是,再次执行得0xFFFFFFFF 1088 | .text:0040262C jnz short loc_402657 ; 唤醒原因 1089 | .text:0040262E movzx eax, byte ptr [ebx+1Dh] ; nt!_KMUTANT 1090 | .text:0040262E ; +0x000 Header : _DISPATCHER_HEADER 1091 | .text:0040262E ; +0x010 MutantListEntry : _LIST_ENTRY 1092 | .text:0040262E ; +0x018 OwnerThread : Ptr32 _KTHREAD 1093 | .text:0040262E ; +0x01c Abandoned : UChar 1094 | .text:0040262E ; +0x01d ApcDisable : UChar 1095 | .text:00402632 sub [esi+_KTHREAD.KernelApcDisable], eax ; 是否禁用内核APC 1096 | .text:00402632 ; 若ApcDisable=0: 减完结果仍然为0 1097 | .text:00402632 ; 若ApcDisable=1: 减完结果一 定不是0 1098 | .text:00402632 ; 只要结果不为0,就禁用内核APC 1099 | .text:00402638 cmp byte ptr [ebx+1Ch], 1 ; 判断是否被放弃使用 1100 | .text:0040263C mov [ebx+18h], esi ; 设置互斥所属线程 1101 | .text:0040263F jz loc_442A97 ; 被弃用,跳转 1102 | ``` 1103 | 1104 | -------------------------------------------------------------------------------- /06事件等待/2520882-20220211162824199-327227111.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/06事件等待/2520882-20220211162824199-327227111.png -------------------------------------------------------------------------------- /06事件等待/2520882-20220211162831246-1280864920.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/06事件等待/2520882-20220211162831246-1280864920.png -------------------------------------------------------------------------------- /06事件等待/2520882-20220211162838959-1627623022.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/06事件等待/2520882-20220211162838959-1627623022.png -------------------------------------------------------------------------------- /06事件等待/2520882-20220211175941247-1806950584.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/06事件等待/2520882-20220211175941247-1806950584.png -------------------------------------------------------------------------------- /06事件等待/image-20230220171234183.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/06事件等待/image-20230220171234183.png -------------------------------------------------------------------------------- /06事件等待/image-20230221104041091.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/06事件等待/image-20230221104041091.png -------------------------------------------------------------------------------- /06事件等待/image-20230221104359682.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/06事件等待/image-20230221104359682.png -------------------------------------------------------------------------------- /06事件等待/image-20230221104635043.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/06事件等待/image-20230221104635043.png -------------------------------------------------------------------------------- /06事件等待/image-20230221111107246.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/06事件等待/image-20230221111107246.png -------------------------------------------------------------------------------- /07APC机制/1827556-20191103170141163-71115727.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/07APC机制/1827556-20191103170141163-71115727.png -------------------------------------------------------------------------------- /07APC机制/image-20230224142512175.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/07APC机制/image-20230224142512175.png -------------------------------------------------------------------------------- /08异常/835440_CA2S8CBBYXKKJ7B.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/08异常/835440_CA2S8CBBYXKKJ7B.png -------------------------------------------------------------------------------- /08异常/image-20230224184604177.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/08异常/image-20230224184604177.png -------------------------------------------------------------------------------- /08异常/image-20230225143409781.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/08异常/image-20230225143409781.png -------------------------------------------------------------------------------- /08异常/image-20230225143525207.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/08异常/image-20230225143525207.png -------------------------------------------------------------------------------- /08异常/image-20230225144037458.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/08异常/image-20230225144037458.png -------------------------------------------------------------------------------- /08异常/image-20230225144809214.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/08异常/image-20230225144809214.png -------------------------------------------------------------------------------- /08异常/image-20230225153154252.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/08异常/image-20230225153154252.png -------------------------------------------------------------------------------- /08异常/image-20230225175242015.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/08异常/image-20230225175242015.png -------------------------------------------------------------------------------- /08异常/image-20230225175253317.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/08异常/image-20230225175253317.png -------------------------------------------------------------------------------- /08异常/image-20230225182333244.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/08异常/image-20230225182333244.png -------------------------------------------------------------------------------- /08异常/image-20230225182342263.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/08异常/image-20230225182342263.png -------------------------------------------------------------------------------- /08异常/image-20230225191306047.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/08异常/image-20230225191306047.png -------------------------------------------------------------------------------- /08异常/image-20230225191407445.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/08异常/image-20230225191407445.png -------------------------------------------------------------------------------- /08异常/image-20230225192811099.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/08异常/image-20230225192811099.png -------------------------------------------------------------------------------- /09内存管理.md: -------------------------------------------------------------------------------- 1 | [toc] 2 | 3 | 4 | 5 | 6 | 7 | # 01.线性地址的管理 8 | 9 | 1. 每个进程都有自己的用户空间需要管理,当我们使用**VirtualAlloc**等函数申请一块固定的地址空间时,首先需要确认这块空间是否被占用,如果该空间已被占用则申请失败。 10 | 2. 用户空间并非像内核空间一样通过一块链表去管理已占用的线性地址空间(效率低), 而是通过**搜索二叉树** 11 | 12 | 13 | 14 | **申请内存的两种方式**: 15 | 16 | 1. 通过**VirtualAlloc/VirtualAllocEx**申请:**Private Memory(独享物理页)** 17 | 2. 通过**CreateFileMapping**进行映射:**Mapped Memory(共享物理页)** 18 | 19 | 进程空间的地址划分: 20 | 21 | | 分区 | x86 32位Windows | 22 | | ------------ | ----------------------- | 23 | | 空指针赋值区 | 0x00000000 - 0x0000FFFF | 24 | | 空指针赋值区 | 0x00010000 - 0x7FFEFFFF | 25 | | 64KB禁入区 | 0x7FFF0000 - 0x7FFFFFFF | 26 | | 内核 | 0x80000000 - 0xFFFFFFFF | 27 | 28 | 29 | 30 | ## 理解用户空间线性地址管理 31 | 32 | 随便找个exe: 33 | 34 | ```c 35 | kd> dt _eprocess 85fd2b88 36 | ntdll!_EPROCESS 37 | ... 38 | +0x11c VadRoot : 0x86140188 Void//入口点,进去后是搜索二叉树,每一个节点记录了一块已被占用的线性地址空间 39 | //对应_MMVAD结构体 40 | +0x120 VadHint : 0x86140188 Void 41 | 42 | //////////////////////////////////////////////////////////////////////////////// 43 | 44 | ``` 45 | 46 | 查看`_MMVAD`结构体: 47 | 48 | ```c 49 | kd> dt _mmvad 0x86140188 50 | nt_exe!_MMVAD 51 | +0x000 StartingVpn : 0x2c60//重要,以页为单位,后面添上三个0即是当前节点所描述的线性地址的起始位置 52 | +0x004 EndingVpn : 0x2c9f//重要,以页为单位,后面添上三个0即是当前节点所描述的线性地址的结束位置 53 | +0x008 Parent : (null) //根节点,不存在父节点 54 | +0x00c LeftChild : 0x863536e0 _MMVAD//左子树 55 | +0x010 RightChild : 0x863392c8 _MMVAD//右子树 56 | +0x014 u : __unnamed//对应_MMVAD_FLAGS结构体 57 | +0x018 ControlArea : 0x0a040004 _CONTROL_AREA//包含该节点所对应的线性地址被谁占用等信息 58 | +0x01c FirstPrototypePte : 0x53646156 _MMPTE 59 | +0x020 LastContiguousPte : 0x00002c20 _MMPTE 60 | +0x024 u2 : __unnamed 61 | 62 | ``` 63 | 64 | 查看**CONTROL_AREA**结构体: 65 | 66 | ```c 67 | kd> dt _CONTROL_AREA 0x865224d8 68 | nt_exe!_CONTROL_AREA 69 | +0x000 Segment : 0xe14eb9b0 _SEGMENT 70 | +0x004 DereferenceList : _LIST_ENTRY [ 0x0 - 0x0 ] 71 | +0x00c NumberOfSectionReferences : 1 72 | +0x010 NumberOfPfnReferences : 0 73 | +0x014 NumberOfMappedViews : 0x12 74 | +0x018 NumberOfSubsections : 1 75 | +0x01a FlushInProgressCount : 0 76 | +0x01c NumberOfUserReferences : 0x13 77 | +0x020 u : __unnamed 78 | +0x024 FilePointer : (null) //文件指针,若为空,表示线性地址指向真正的物理页;如果不为null就是自己分配的内存 79 | +0x028 WaitingForDeletion : (null) 80 | +0x02c ModifiedWriteCount : 0 81 | +0x02e NumberOfSystemCacheViews : 0 82 | kd> dt _FILE_OBJECT 83 | nt_exe!_FILE_OBJECT 84 | +0x000 Type : Int2B 85 | +0x002 Size : Int2B 86 | +0x004 DeviceObject : Ptr32 _DEVICE_OBJECT 87 | +0x008 Vpb : Ptr32 _VPB 88 | +0x00c FsContext : Ptr32 Void 89 | +0x010 FsContext2 : Ptr32 Void 90 | +0x014 SectionObjectPointer : Ptr32 _SECTION_OBJECT_POINTERS 91 | +0x018 PrivateCacheMap : Ptr32 Void 92 | +0x01c FinalStatus : Int4B 93 | +0x020 RelatedFileObject : Ptr32 _FILE_OBJECT 94 | +0x024 LockOperation : UChar 95 | +0x025 DeletePending : UChar 96 | +0x026 ReadAccess : UChar 97 | +0x027 WriteAccess : UChar 98 | +0x028 DeleteAccess : UChar 99 | +0x029 SharedRead : UChar 100 | +0x02a SharedWrite : UChar 101 | +0x02b SharedDelete : UChar 102 | +0x02c Flags : Uint4B 103 | +0x030 FileName : _UNICODE_STRING//线性地址属于主模块 104 | +0x038 CurrentByteOffset : _LARGE_INTEGER 105 | +0x040 Waiters : Uint4B 106 | +0x044 Busy : Uint4B 107 | +0x048 LastLock : Ptr32 Void 108 | +0x04c Lock : _KEVENT 109 | +0x05c Event : _KEVENT 110 | +0x06c CompletionContext : Ptr32 _IO_COMPLETION_CONTEXT 111 | ``` 112 | 113 | **查看MMVAD_FLAGS结构体** 114 | 115 | ```c 116 | kd> dt _MMVAD_FLAGS 0x86313578+14 117 | nt_exe!_MMVAD_FLAGS 118 | +0x000 CommitCharge : 0y0000000000000000000 (0) 119 | +0x000 PhysicalMapping : 0y0 120 | +0x000 ImageMap : 0y0//为1表示镜像文件(可执行文件),0表示其他 121 | +0x000 UserPhysicalPages : 0y0 122 | +0x000 NoChange : 0y0 123 | +0x000 WriteWatch : 0y0 124 | +0x000 Protection : 0y00100 (0x4)//表示内存权限 125 | +0x000 LargePages : 0y0 126 | +0x000 MemCommit : 0y0 127 | +0x000 PrivateMemory : 0y1//0表示Mapped Memory 128 | ``` 129 | 130 | **遍历所有节点**: 131 | 132 | ```c 133 | kd> !vad 0x86313578 (随便找了个) 134 | VAD Level Start End Commit 135 | 86322b18 3 10 10 1 Private READWRITE 136 | 864ac328 2 20 20 1 Private READWRITE 137 | 86127360 5 30 3f 8 Private READWRITE 138 | 86330d60 4 40 7f 4 Private READWRITE 139 | 85fb1188 3 80 82 0 Mapped READONLY Pagefile section, shared commit 0x3 140 | 8611ee50 4 90 91 0 Mapped READONLY Pagefile section, shared commit 0x2 141 | 85fb7a08 1 a0 19f 23 Private READWRITE 142 | 86322cf8 4 1a0 1af 6 Private READWRITE 143 | 8611ee20 3 1b0 1bf 0 Mapped READWRITE Pagefile section, shared commit 0x3 144 | 8611f6d8 4 1c0 1d5 0 Mapped READONLY \WINDOWS\system32\unicode.nls 145 | 863129d0 2 1e0 220 0 Mapped READONLY \WINDOWS\system32\locale.nls 146 | 86312910 4 230 270 0 Mapped READONLY \WINDOWS\system32\sortkey.nls 147 | 86313488 3 280 285 0 Mapped READONLY \WINDOWS\system32\sorttbls.nls 148 | 86313578 0 290 2d0 0 Mapped READONLY Pagefile section, shared commit 0x41 149 | 86312a00 4 2e0 3a7 0 Mapped EXECUTE_READ Pagefile section, shared commit 0x8 150 | 85f96608 5 3b0 3b0 1 Private READWRITE 151 | 864583f8 3 3c0 3c0 1 Private READWRITE 152 | 86124128 5 3d0 3df 5 Private READWRITE 153 | 8611ef10 4 3e0 3e1 0 Mapped READONLY Pagefile section, shared commit 0x2 154 | 85fb1bc8 6 3f0 3f0 0 Mapped READWRITE Pagefile section, shared commit 0x1 155 | 85fb1e68 5 400 401 0 Mapped READONLY Pagefile section, shared commit 0x2 156 | 85fbbd98 2 410 41f 8 Private READWRITE 157 | 8612f808 4 420 42f 4 Private READWRITE 158 | 85fa8e50 3 430 432 0 Mapped READONLY \WINDOWS\system32\ctype.nls 159 | 85fb9e28 5 440 47f 3 Private READWRITE 160 | 8631b8e0 4 480 582 0 Mapped READONLY Pagefile section, shared commit 0x103 161 | 863128b0 6 590 88f 0 Mapped EXECUTE_READ Pagefile section, shared commit 0x26 162 | 85fb79c8 5 890 90f 1 Private READWRITE 163 | 85fb1fa8 7 910 94f 0 Mapped READWRITE Pagefile section, shared commit 0x10 164 | 85fb1f78 6 950 95d 0 Mapped READWRITE Pagefile section, shared commit 0xe 165 | 85fc1610 7 960 a5f 123 Private READWRITE 166 | 86321260 8 a60 a63 0 Mapped READWRITE Pagefile section, shared commit 0x4 167 | 8631ccc8 9 a80 aff 0 Mapped READWRITE Pagefile section, shared commit 0x7 168 | 86476b08 1 1000 101e 3 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\calc.exe 169 | 86313458 8 58fb0 59179 10 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\AppPatch\AcGenral.dll 170 | 863133f8 9 5adc0 5adf6 2 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\uxtheme.dll 171 | 86312a30 7 5cc30 5cc55 21 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\shimeng.dll 172 | 8611da38 11 62c20 62c28 2 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\lpk.dll 173 | 85fb2b10 13 73640 7366d 2 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\MSCTFIME.IME 174 | 863158f8 12 73fa0 7400a 17 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\usp10.dll 175 | 85fb2c10 13 74680 746cb 3 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\MSCTF.dll 176 | 85faf260 10 759d0 75a7e 3 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\userenv.dll 177 | 86313518 11 76300 7631c 2 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\imm32.dll 178 | 863128e0 9 76990 76acd 8 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\ole32.dll 179 | 86315830 8 76b10 76b39 3 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\winmm.dll 180 | 85fa8e20 9 770f0 7717a 4 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\oleaut32.dll 181 | 86313398 11 77180 77282 2 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.6028_x-ww_61e65202\comctl32.dll 182 | 85fabd48 10 77bb0 77bc4 2 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\msacm32.dll 183 | 863134e8 11 77bd0 77bd7 2 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\version.dll 184 | 86313428 6 77be0 77c37 8 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\msvcrt.dll 185 | 8613c0e0 5 77d10 77d9f 3 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\user32.dll 186 | 8611e1d0 4 77da0 77e48 6 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\advapi32.dll 187 | 86312970 5 77e50 77ee2 2 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\rpcrt4.dll 188 | 85fa83d8 7 77ef0 77f39 3 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\gdi32.dll 189 | 863133c8 8 77f40 77fb5 2 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\shlwapi.dll 190 | 863129a0 6 77fc0 77fd0 2 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\secur32.dll 191 | 864b70d8 3 7c800 7c91d 6 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\kernel32.dll 192 | 8611eee0 2 7c920 7c9b2 5 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\ntdll.dll 193 | 863135a8 5 7d590 7dd83 31 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\shell32.dll 194 | 863134b8 4 7f6f0 7f7ef 0 Mapped EXECUTE_READ Pagefile section, shared commit 0x7 195 | 85fa21a0 3 7ffa0 7ffd2 0 Mapped READONLY Pagefile section, shared commit 0x33 196 | 86305638 4 7ffdd 7ffdd 1 Private READWRITE 197 | 864a8530 5 7ffdf 7ffdf 1 Private READWRITE 198 | 199 | Total VADs: 63, average level: 6, maximum depth: 13 200 | Total private commit: 0x159 pages (1380 KB) 201 | Total shared commit: 0x1e2 pages (1928 KB) 202 | ``` 203 | 204 | ## 总结 205 | 206 | 1. 所有的线性地址空间是需要管理的(哪些地址是占用的,哪些地址是未占用的) 207 | 208 | 2. 所有用户线性地址空间通过搜索二叉树进行管理(占用大小,占用方式,内存属性) 209 | 210 | 3. 所有已占用的线性地址可以分为两类 211 | 212 | 1. VirtualAlloc分配的普通内存 213 | 214 | 2. 文件映射(Mapped)的内存(例如dll/exe/txt等) 215 | 216 | 4. 传统的模块隐藏技术,终究会在VadRoot中留下痕迹,假设摘除,操作系统会误认为该地址空间未被分配,从而产生非预期中的错误 217 | 218 | # 02.Private Memory 219 | 220 | 通过**VirtualAlloc/VirtualAllocEx**申请的内存,叫做Private Memory 221 | 222 | 函数原型: 223 | 224 | ```c 225 | LPVOID VirtualAlloc{ 226 | LPVOID lpAddress, // 要分配的内存区域的地址,填0则随机分配一块符合条件的地址 227 | DWORD dwSize, // 分配的大小,4kb对齐 228 | DWORD flAllocationType, // 分配的类型 229 | // MEM_RESERVE:只保留线性地址,不分配物理页 230 | // MEM_COMMIT:既保留线性地址,又分配物理页 231 | DWORD flProtect // 该内存的初始保护属性 232 | }; 233 | ``` 234 | 235 | 代码: 236 | 237 | ```c 238 | #include 239 | #include 240 | 241 | LPVOID lpAddress; 242 | 243 | int main() 244 | { 245 | printf("程序运行了...内存还没有申请\n"); 246 | getchar(); 247 | 248 | lpAddress = VirtualAlloc(NULL, 0x1000*2, MEM_COMMIT, PAGE_READWRITE); 249 | printf("内存地址:%x\n", lpAddress); 250 | 251 | getchar(); 252 | return 0; 253 | } 254 | ``` 255 | 256 | 可以对比`VirtualAlloc`前后的不同,这里就不贴图了。 257 | 258 | 259 | 260 | # 03.Mapped Memory 261 | 262 | 1. 通过`CreateFileMapping`映射的内存,叫做Mapped Memory,一个进程中大部分的内存都属于Mapped Memory 263 | 2. Mapped Memory可以分为两类 264 | 1. 共享内存:当内存为共享内存时,本质是共享一份物理页 265 | 2. 共享文件:当内存为共享文件时,这块内存可能被映射到多个进程空间中,但真正占用的物理页只有一份 266 | 3. 无论是共享内存还是文件,在底层实现都是一样的,当我们需要共享物理页的时候,系统只需将物理页准备好,当我们需要共享文件时,系统先将物理页准备好,然后将物理页与文件进行关联 267 | 268 | 269 | 270 | ## 共享内存 271 | 272 | 代码1: 273 | 274 | ```c 275 | #include 276 | #include 277 | 278 | #define MapFileName "共享内存" 279 | 280 | int main() 281 | { 282 | //内核对象:1.物理页 2. 文件 283 | //准备一块内存,若第一个参数为INVALID_HANDLE_VALUE(-1)表示共享物理页 284 | HANDLE g_hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, BUFSIZ, MapFileName); 285 | 286 | //将物理页与线性地址进行映射 287 | LPTSTR g_lpBuff = (LPTSTR)MapViewOfFile(g_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUFSIZ); 288 | 289 | *(PDWORD)g_lpBuff = 0x12345678; 290 | 291 | printf("A进程写入地址,内容:%p - %x", g_lpBuff, *(PDWORD)g_lpBuff); 292 | 293 | getchar(); 294 | return 0; 295 | } 296 | ``` 297 | 298 | 代码2: 299 | 300 | ```c 301 | #include 302 | #include 303 | 304 | #define MapFileName "共享内存" 305 | 306 | int main() 307 | { 308 | //内核对象:1.物理页 2. 文件 309 | HANDLE g_hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, MapFileName); 310 | 311 | //将物理页与线性地址进行映射 312 | LPTSTR g_lpBuff = (LPTSTR)MapViewOfFile(g_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUFSIZ); 313 | 314 | 315 | printf("B进程读取地址,内容:%p - %x", g_lpBuff, *(PDWORD)g_lpBuff); 316 | 317 | getchar(); 318 | return 0; 319 | } 320 | ``` 321 | 322 | 323 | 324 | ## 共享文件 325 | 326 | 示例代码,ret的地方断点: 327 | 328 | ```c 329 | #include 330 | #include 331 | 332 | int main() 333 | { 334 | //内核对象:1.物理页 2. 文件 335 | HANDLE g_hFile = CreateFile("C:\\NOTEPAD.EXE",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); 336 | 337 | HANDLE g_hMapFile = CreateFileMapping(g_hFile,NULL,PAGE_READWRITE,0, BUFSIZ,NULL); 338 | 339 | //将物理页与线性地址进行映射 340 | LPTSTR g_lpBuff = (LPTSTR)MapViewOfFile(g_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUFSIZ); 341 | 342 | return 0; 343 | } 344 | 345 | ``` 346 | 347 | 可以看到: 348 | 349 | ![image-20230226183309832](./09内存管理/image-20230226183309832.png) 350 | 351 | ```c 352 | 86128f20 1 10 10 1 Private READWRITE 353 | 85f9d600 2 20 20 1 Private READWRITE 354 | 860362f8 0 30 12f 3 Private READWRITE 355 | 8645de68 3 130 132 0 Mapped READONLY Pagefile section, shared commit 0x3 356 | 86128f70 2 140 23f 3 Private READWRITE 357 | 85f96588 4 240 24f 6 Private READWRITE 358 | 86354738 3 250 25f 0 Mapped READWRITE Pagefile section, shared commit 0x3 359 | 863aef38 5 260 275 0 Mapped READONLY \WINDOWS\system32\unicode.nls 360 | 86358510 4 280 2c0 0 Mapped READONLY \WINDOWS\system32\locale.nls 361 | 863584b0 6 2d0 310 0 Mapped READONLY \WINDOWS\system32\sortkey.nls 362 | 85fa69b8 5 320 325 0 Mapped READONLY \WINDOWS\system32\sorttbls.nls 363 | 8645de08 7 330 370 0 Mapped READONLY Pagefile section, shared commit 0x41 364 | 8614a3f8 6 380 38f 3 Private READWRITE 365 | 8602e848 7 390 392 0 Mapped READONLY \WINDOWS\system32\ctype.nls 366 | 861451e0 8 3a0 3a0 0 Mapped READWRITE \NOTEPAD.EXE 367 | 86128f40 1 400 42c 8 Mapped Exe EXECUTE_WRITECOPY \Documents and Settings\Administrator\桌面\VC6.0green\MyProjects\test\Debug\test.exe 368 | 863a6b08 3 7c800 7c91d 6 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\kernel32.dll 369 | 85f968a0 2 7c920 7c9b2 5 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\ntdll.dll 370 | 863aefd8 4 7f6f0 7f7ef 0 Mapped EXECUTE_READ Pagefile section, shared commit 0x7 371 | 85f96870 3 7ffa0 7ffd2 0 Mapped READONLY Pagefile section, shared commit 0x33 372 | ``` 373 | 374 | 375 | 376 | ### Mapped Exe 377 | 378 | 1. 当一个程序通过`LoadLibrary`进行加载时,此时该文件所在的线性地址空间的属性为Mapped Exe,权限为`EXECUTE_WRITECOPY` 379 | 2. 由于权限为`EXECUTE_WRITECOPY`的地址空间是需要共享给所有程序使用的,因此当我们对权限为`EXECUTE_WRITECOPY`的线性地址空间的任何位置进行修改时,系统会先给这块内存重新映射一份物理页,然后再进行修改 380 | 381 | 示例代码: 382 | 383 | ```c 384 | #include 385 | #include 386 | 387 | int main() 388 | { 389 | HMODULE hModule = LoadLibrary("C:\\NOTEPAD.EXE"); 390 | 391 | return 0; 392 | } 393 | ``` 394 | 395 | ## 总结 396 | 397 | 1)线性地址分为三类:私有内存 | 共享内存 | 共享文件 398 | 2)共享内存和共享文件本质相同,都是分配了一块物理页,不同的是共享文件将物理页和文件关联了起来 399 | 3)传统的模块隐藏技术很难在VadRoot中进行隐藏(脱钩可能会导致程序崩溃),除非通过VirtualAlloc分配私有内存,手动将文件进行拉伸与贴入等一系列操作,此时能够大大增加寻找该模块的难度 400 | 401 | # 04.物理内存管理 402 | 403 | 404 | 405 | 32位最大物理内存: 406 | 407 | 1. 10-10-12分页 最多识别物理内存为4GB 408 | 2. 2-9-9-12分页 最多识别物理内存为64GB 409 | 410 | 操作系统的 `_ExVerifySuite()` 函数限制了它无法超越4GB(网上有补丁可以突破4GB) 411 | 412 | 实际物理内存: 413 | 414 | > MmNumberOfPhysicalPages * 4 = 物理内存 415 | 416 | 可以看到一共7FF6C个物理页,乘4后得到KB,与人物管理器中的一致。 417 | 418 | ```c 419 | kd> dd MmNumberOfPhysicalPages 420 | 80563128 0003ff6a 00000040 00000000 7fff0000 421 | 80563138 80000000 7ffeffff 00000000 00000000 422 | 80563148 00000000 00000000 00000000 00000000 423 | 80563158 00000000 00000000 00000004 00000000 424 | 425 | ``` 426 | 427 | 428 | 429 | ## 物理内存管理 430 | 431 | 是一个全局数组: 432 | 433 | ```c 434 | 数组指针:_MMPFN* MmPfnDatabase 435 | 数组长度:MmNumberOfPhysicalPages 436 | ``` 437 | 438 | 81000000~(81000000+0x18)描述的就是第一个物理页的信息,8100001C~(8100001C+0x18)是第二个物理页的描述信息,以此类推。 439 | 440 | `80c86000+1c*索引 == 这个物理页对应的_MMPFN结构` 441 | 442 | ```c 443 | kd> dd MmPfnDatabase 444 | 805630c8 81000000 ffffffff 00000006 0000003f 445 | 805630d8 0000cfc5 00030c23 00020ae2 0000155f 446 | 805630e8 0000cb3e 00000000 000114f4 00009737 447 | 805630f8 00001f9c 00000000 00000000 000000c0 448 | 80563108 0000000c 00000000 00000000 0000001e 449 | 80563118 000000fa 0002f6b3 0003ffff 0003ffff 450 | ``` 451 | 452 | ## PFN 453 | 454 | `_MMPFN`结构体: 455 | 456 | ```c 457 | kd> dt _MMPFN 458 | nt!_MMPFN 459 | +0x000 u1 : __unnamed 460 | +0x004 PteAddress : Ptr32 _MMPTE 461 | +0x008 u2 : __unnamed 462 | +0x00c u3 : __unnamed 463 | +0x010 OriginalPte : _MMPTE 464 | +0x018 u4 : __unnamed 465 | 466 | typedef struct _MMPFN 467 | { 468 | union 469 | { 470 | PFN_NUMBER Flink; 471 | ULONG WsIndex;//该页面在进程工作集链表中的索引 472 | PKEVENT Event; 473 | NTSTATUS ReadStatus; 474 | SINGLE_LIST_ENTRY NextStackPfn; 475 | 476 | // HACK for ROSPFN 477 | SWAPENTRY SwapEntry; 478 | } u1; 479 | PMMPTE PteAddress;//执行此页面的PTE的虚拟地址 480 | union 481 | { 482 | PFN_NUMBER Blink; 483 | ULONG_PTR ShareCount;//指向该页面的PTE数量 484 | } u2; 485 | union 486 | { 487 | struct 488 | { 489 | USHORT ReferenceCount;//代表这个页面必须要保留在内存中的引用计数 490 | MMPFNENTRY e1; 491 | }; 492 | struct 493 | { 494 | USHORT ReferenceCount; 495 | USHORT ShortFlags; 496 | } e2; 497 | } u3; 498 | union 499 | { 500 | MMPTE OriginalPte;//包含了指向此页面的PTE的原始内容 501 | LONG AweReferenceCount; 502 | 503 | // HACK for ROSPFN 504 | PMM_RMAP_ENTRY RmapListHead; 505 | }; 506 | union 507 | { 508 | ULONG_PTR EntireFrame; 509 | struct 510 | { 511 | ULONG_PTR PteFrame:25; 512 | ULONG_PTR InPageError:1; 513 | ULONG_PTR VerifierAllocation:1; 514 | ULONG_PTR AweAllocation:1; 515 | ULONG_PTR Priority:3; 516 | ULONG_PTR MustBeCached:1; 517 | }; 518 | } u4;//指向该页面的PTE所在的页表页面的物理页帧编号,以及一些标志位 519 | 520 | u3.e1.PageLocation 这个成员标识了当前物理页空闲状态(空闲:使用中,两大类) 521 | 0:MmZeroedPageListHead //零化 522 | 1:MmFreePageListHead //空闲 523 | 2:MmStandbyPageListHead //备用 524 | 3:MmModifiedPageListHead //修改 OriginalPte.u.Soft.Prototype=1 或者 外存都会在这 525 | 4:MmModifiedNoWritePageListHead//已修改但不写出 526 | 5:MmBadPageListHead //损坏 527 | ``` 528 | 529 | ### 零化链表 530 | 531 | `MmPfnDatabase`:第一个物理页描述信息:`81000000` 532 | 533 | ```c 534 | kd> dd MmPfnDatabase l1 535 | 805630c8 81000000 536 | ``` 537 | 538 | 零化链表: 539 | 540 | ```c 541 | kd> dd MmZeroedPageListHead l4 542 | 805528e8 0002949c 00000000 00023a24 00023ab3 543 | ``` 544 | 545 | 第一个零化链表: 546 | 547 | ```c 548 | kd> dd 81000000 + 0x1C*00023a24 l4 549 | 813e5bf0 00023a64 0011d120 ffffffff 00003000 550 | ``` 551 | 552 | 零化链表: 553 | 554 | ![image-20230227102011045](./09内存管理/image-20230227102011045.png) 555 | 556 | 结构如下: 557 | 558 | ![image-20230227102049345](./09内存管理/image-20230227102049345.png) 559 | 560 | 561 | 562 | ```c 563 | kd> dt _eprocess 86104020 564 | ntdll!_EPROCESS 565 | +0x1f8 Vm : _MMSUPPORT 566 | kd> dt _MMSUPPORT 567 | nt_exe!_MMSUPPORT 568 | +0x000 LastTrimTime : _LARGE_INTEGER 569 | +0x008 Flags : _MMSUPPORT_FLAGS 570 | +0x00c PageFaultCount : Uint4B 571 | +0x010 PeakWorkingSetSize : Uint4B 572 | +0x014 WorkingSetSize : Uint4B 573 | +0x018 MinimumWorkingSetSize : Uint4B//最小的物理页大小 574 | +0x01c MaximumWorkingSetSize : Uint4B//最大的物理页大小 575 | +0x020 VmWorkingSetList : Ptr32 _MMWSLz//这个成员可以找到这个进程使用的所有物理页 576 | +0x024 WorkingSetExpansionLinks : _LIST_ENTRY 577 | +0x02c Claim : Uint4B 578 | +0x030 NextEstimationSlot : Uint4B 579 | +0x034 NextAgingSlot : Uint4B 580 | +0x038 EstimatedAvailable : Uint4B 581 | +0x03c GrowthSinceLastEstimate : Uint4B 582 | ///////////////////////////////////////////////////////////////////////// 583 | nt!_MMWSL 584 | +0x000 Quota : 0 585 | +0x004 FirstFree : 0x1e 586 | +0x008 FirstDynamic : 0xa 587 | +0x00c LastEntry : 0x217 588 | +0x010 NextSlot : 7 589 | +0x014 Wsle : 0xc0883cfc _MMWSLE //物理页起始地址 590 | +0x018 LastInitializedWsle : 0x4c0 //物理页个数 591 | +0x01c NonDirectCount : 0x33 592 | +0x020 HashTable : 0xc0a84000 _MMWSLE_HASH 593 | +0x024 HashTableSize : 0x200 594 | +0x028 NumberOfCommittedPageTables : 2 595 | +0x02c HashTableStart : 0xc0a84000 Void 596 | +0x030 HighestPermittedHashAddress : 0xc0e00000 Void 597 | +0x034 NumberOfImageWaiters : 0 598 | +0x038 VadBitMapHint : 0x16 599 | +0x03c UsedPageTableEntries : [1536] 0x34 600 | +0xc3c CommittedPageTables : [48] 1 601 | 602 | ``` 603 | 604 | # 05.缺页异常 605 | 606 | PTE页表: 607 | 608 | ![image-20230227110744432](./09内存管理/image-20230227110744432.png) 609 | 610 | P位表示当前页是否有效 611 | 612 | > Windows是只有正在被使用的线性地址才会给你挂上物理页,如果你的线性地址隔了一段时间没使用或者当前的物理页快被占用完了,这时它会将你这些物理页的数据拿出来存到硬盘上。 613 | > 614 | > 右键我的电脑 -> 属性 -> 高级 -> 性能下的设置 -> 高级 ->虚拟内存更改 615 | > 设置虚拟内存后它会在你的c盘下生成一个pagefile.sys,它的大小刚好是你设置的虚拟内存大小。 616 | > 617 | > 当你的物理页不够用了,这时系统会将物理页里的数据放到pagefile.sys这个文件中,再将这个物理页跟程序使用。 618 | > 619 | > 如果我们在某个程序中使用了0x12345678这个线性地址,它的物理页被存放的pagefile.sys了,如果我门在次使用这个地址就出问题了,这时就需要用到缺页异常了 620 | 621 | 当线性地址对应的物理页被存储到文件中时,PTE结构被拓展为以下四种情形: 622 | 623 | ![image-20230227111808658](./09内存管理/image-20230227111808658.png) 624 | 625 | > 图a:位于页面文件中 626 | > 当你的线性地址的物理页被存放到页面文件(pagefile.sys)中的时候,你的PTE就会变成这样 627 | > 628 | > CPU访问了这地址你的p:0,进入缺页异常处理程序,缺页异常位于idt表里的E号中断。 629 | > 630 | > 进入缺页异常处理它会回头查看你的这个PTE,这时地址时发现你的1-9位,12-31位都是有值的,它就会知道你这个线性地址是有效的,只不过数据放到页面文件里了 631 | > 632 | > 异常处理程序会到pagefile.sys中,按照PTE上描述的页面文件偏移将页的数据取出来挂到一个新的物理页上,将12-31位改为新的物理页地址,再将p=1 633 | > 634 | > 图b:要求0页面 635 | > 页面尚未分配,下次访问时请求一个0页面 636 | > 637 | > 图c:转移 638 | > 页面在物理内存中,但已被转移到某个物理页面链表中,可以通过查询_MMPFN数据库获取实际情况 639 | > 640 | > 图d:缺页异常处理发现你PTE全部为0就会去查VAD,发现这个线性地址已经分配了它会帮你把物理页挂上,如果这个线性地址没有分配就会报0xC0000005。(具体看 “保留与提交的误区” ) 641 | 642 | ## 保留与提交 643 | 644 | `VirtualAlloc`: 645 | 646 | ```c 647 | LPVOID VirtualAlloc( 648 | LPVOID lpAddress, // 要分配的内存区域的地址 649 | DWORD dwSize, // 分配的大小 650 | DWORD flAllocationType, // 类型:MEM_RESERVE MEM_COMMIT 651 | DWORD flProtect // 该内存的初始保护属性 652 | ); 653 | 654 | // MEM_RESERVE:只保留线性地址,不分配物理页 655 | // MEM_COMMIT:既保留线性地址,又分配物理页 656 | ``` 657 | 658 | 示例代码: 659 | 660 | ```c 661 | #include 662 | #include 663 | 664 | int main() 665 | { 666 | LPVOID pAddr = VirtualAlloc(NULL, 0x1000*8, MEM_COMMIT, PAGE_READWRITE); 667 | printf("%p\n", pAddr); 668 | getchar(); 669 | *(PDWORD)pAddr = 0x12345678; 670 | getchar(); 671 | return 0; 672 | } 673 | ``` 674 | 675 | 结果: 676 | 677 | ![image-20230304142407074](./09内存管理/image-20230304142407074.png) 678 | 679 | 查看该地址有没有物理页: 680 | 681 | ```c 682 | kd> !process 0 0 683 | Failed to get VadRoot 684 | PROCESS 86301020 SessionId: 0 Cid: 023c Peb: 7ffd7000 ParentCid: 0238 685 | DirBase: 06bc01c0 ObjectTable: e1bbbd20 HandleCount: 10. 686 | Image: test.exe 687 | 688 | kd> !vtop 06bc01c0 3a0000 689 | X86VtoP: Virt 00000000003a0000, pagedir 0000000006bc01c0 690 | X86VtoP: PAE PDPE 0000000006bc01c0 - 000000002aa4d801 691 | X86VtoP: PAE PDE 000000002aa4d008 - 000000002aaff867 692 | X86VtoP: PAE PTE 000000002aaffd00 - 0000000000000000//这里,没有 693 | X86VtoP: PAE zero PTE 694 | Virtual address 3a0000 translation fails, error 0xD0000147. 695 | ``` 696 | 697 | 敲个回车后: 698 | 699 | ```c 700 | kd> !vtop 06bc01c0 3a0000 701 | X86VtoP: Virt 00000000003a0000, pagedir 0000000006bc01c0 702 | X86VtoP: PAE PDPE 0000000006bc01c0 - 000000002aa4d801 703 | X86VtoP: PAE PDE 000000002aa4d008 - 000000002aaff867 704 | X86VtoP: PAE PTE 000000002aaffd00 - 800000002b62e867//已经挂上了 705 | X86VtoP: PAE Mapped phys 000000002b62e000 706 | Virtual address 3a0000 translates to physical address 2b62e000. 707 | ``` 708 | 709 | 也可以这样看: 710 | 711 | ```c 712 | !dd 06bc01c0 + 3a0*4 713 | ``` 714 | 715 | 716 | 717 | 718 | 719 | ## 写拷贝(EXECUTE_WRITECOPY) 720 | 721 | 722 | 723 | ![image-20230304144643458](./09内存管理/image-20230304144643458.png) 724 | 725 | 726 | 727 | 先将PTE的R/W=0,`_MMVAD_FLAGS`设为`EXECUTE_WRITECOPY` 728 | 729 | 当你HOOK一些属性为EXECUTE_WRITECOPY的模块时: 730 | 731 | 1. 修改它的物理页,这时它PTE.R/W为0就会触发缺页异常 732 | 2. 进入异常处理程序发现PTE.R/W=0,查这个页对应的VAD发现 Protection 为写拷贝 733 | 3. 创建一份新的物理页,修改的数据放到新的物理页,将你的线性地址会指向这个新的物理页。 734 | 735 | 如果写驱动程序将它的PTE.R/W强行修改为1,这样它就不会触发缺页异常,可实现A进程中hook了这个模块,所有使用这个模块的进程也会被HOOK。 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | -------------------------------------------------------------------------------- /09内存管理/image-20230226183309832.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/09内存管理/image-20230226183309832.png -------------------------------------------------------------------------------- /09内存管理/image-20230227102011045.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/09内存管理/image-20230227102011045.png -------------------------------------------------------------------------------- /09内存管理/image-20230227102049345.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/09内存管理/image-20230227102049345.png -------------------------------------------------------------------------------- /09内存管理/image-20230227110744432.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/09内存管理/image-20230227110744432.png -------------------------------------------------------------------------------- /09内存管理/image-20230227111808658.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/09内存管理/image-20230227111808658.png -------------------------------------------------------------------------------- /09内存管理/image-20230304142407074.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/09内存管理/image-20230304142407074.png -------------------------------------------------------------------------------- /09内存管理/image-20230304144643458.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/09内存管理/image-20230304144643458.png -------------------------------------------------------------------------------- /10消息机制.md: -------------------------------------------------------------------------------- 1 | [toc] 2 | 3 | 4 | 5 | 6 | 7 | # 1.消息队列 8 | 9 | ## 消息队列 10 | 11 | 本质上是一种数据结构,先进先出。 12 | 13 | ## 消息队列在哪 14 | 15 | 16 | 17 | ### Linux:专用进程 18 | 19 | 1. 使用专用进程捕获所有消息 20 | 2. 判断消息所属进程,进行分发,将消息分配到目标进程的消息队列中 21 | 22 | ![image-20230304145550736](./10消息机制/image-20230304145550736.png) 23 | 24 | 25 | 26 | ### Windows:GUI线程 27 | 28 | KTHREAD结构体: 29 | 30 | ```c 31 | kd> dt _KTHREAD 32 | ntdll!_KTHREAD 33 | ... 34 | +0x130 Win32Thread //若当前程序为控制台程序且无使用任何图形界面相关API,该成员为空 35 | //若当前程序使用了图形界面相关的API,该成员指向一个结构体,该结构体包含了消息队列 36 | ... 37 | ``` 38 | 39 | **GUI**:微软提供的与图形界面相关的API,称为GUI 40 | **GDI**:自定义的用于图形界面相关的API,称为GDI 41 | 42 | 43 | 44 | **GUI线程**: 45 | 46 | 1. 当线程刚创建的时候,都是普通线程: 47 | `Thread.ServiceTable`指向`KeServiceDescriptorTable` 48 | 2. 当线程第一次调用`Win32k.sys`(调用号大于0x100)时,会调用一个函数,将当前线程转换成GUI线程:`PsConvertToGuiThread` 49 | 主要做几件事: 50 | 1. 扩充内核栈,必须换成64KB的大内核栈,因为普通内核栈只有12KB大小 51 | 2. 创建一个包含消息队列的结构体,并挂到KTHREAD上 52 | 3. 将`Thread.ServiceTable`指向`KeServiceDescriptorTableShadow`(只有当调用GUI时,才会指向`SSDTShadow`) 53 | 4. 把需要的内存数据映射到本进程空间 54 | 55 | 56 | 57 | ### Win32Thread 58 | 59 | 位于KTHREAD,若当前程序使用了图形界面相关的API,该成员指向一个结构体,其中包含了当前线程的消息队列:**THREADINFO** 60 | 61 | ```c 62 | //FROM ReactOS v0.4.13 63 | typedef struct _THREADINFO{ 64 | ... 65 | struct _USER_MESSAGE_QUEUE* MessageQueue; //消息队列 66 | ... 67 | } THREADINFO; 68 | ``` 69 | 70 | 71 | 72 | ## 总结 73 | 74 | 1. 消息队列存储在**0环**,通过**KTHREAD.Win32Thread**可以找到 75 | 2. 并不是所有线程都要消息队列,只有GUI线程才有消息队列 76 | 3. 一个GUI线程对应1个消息队列 77 | 78 | 79 | 80 | # 2.窗口与线程 81 | 82 | 83 | 84 | ## 消息去处 85 | 86 | 1. 当我们使用鼠标某个窗口进行点击与滑动时,都会产生一个消息,消息会进入当前窗口对应线程的消息队列中 87 | 2. 当我们编写程序时,并不会去特地启动两个线程去监控鼠标和键盘,`w32k.sys`负责了这个事情 88 | 89 | > 当初始化**w32k.sys**这个模块时,会调用一个叫做**InitInputImpl**的函数 90 | > 这个函数会启动两个线程,分别用来监控鼠标和键盘,这两个线程都是0环的线程 91 | > 平时我们的电脑遭遇“死机”时,常常是屏幕动不了,鼠标还能动,这正式由于鼠标是有一个独立的线程在监控它的行动 92 | 93 | 当调用`CreateWindow`时,该函数实际上是一个宏,`CreateWindowA`实际对应`CreateWindowExA`函数,`CreateWindowW`对应`CreateWindowExW`函数。 94 | 95 | 最终窗口在0环被画出(由w32k.sys实现) 96 | 97 | ## 窗口对象 98 | 99 | 1. 每个窗口对应一个`WINDOW_OBJECT`结构体,位于0环,包含当前窗口所有信息 100 | 2. 除了大窗口之外,窗口中的每个控件也都是一个窗口,也分别对应一个`WINDOW_OBJECT`结构体 101 | 3. 一个窗口内包含着许多个窗口,按钮,对话框也都属于窗口,属于同一个线程 102 | 4. 一个线程可以包含多个窗口,但每个窗口只能属于一个线程 103 | 104 | ```c 105 | //FROM ReactOS v3.12 106 | typedef struct _WINDOW_OBJECT 107 | { 108 | ... 109 | PWND Wnd; //包含大量窗口信息 110 | PTHREADINFO pti; //线程 111 | ... 112 | } 113 | typedef struct _WND 114 | { 115 | ... 116 | /* Style. */ 117 | DWORD style; //包含窗口风格/后一个窗口/前一个窗口/父窗口/子窗口等信息 118 | ... 119 | } WND, *PWND; 120 | ``` 121 | 122 | 123 | 124 | # 3.消息的接收和分发 125 | 126 | ## 消息队列 127 | 128 | 消息队列共有七组,用于存放不同类型的消息。 129 | 130 | ```c 131 | 1)SentMessagesListHead //接收SendMessage发来的消息 132 | 2)PostedMessagesListHead //接收PostMessage发来的消息 133 | 3)HardwareMessagesListHead //接收键盘、鼠标等硬件设备的消息 134 | ... 135 | ``` 136 | 137 | 完整队列: 138 | 139 | ```c 140 | //ReactOS v3.12 141 | typedef struct _USER_MESSAGE_QUEUE 142 | { 143 | ... 144 | /* Owner of the message queue */ 145 | struct _ETHREAD *Thread; 146 | /* Queue of messages sent to the queue. */ 147 | LIST_ENTRY SentMessagesListHead; 148 | /* Queue of messages posted to the queue. */ 149 | LIST_ENTRY PostedMessagesListHead; 150 | /* Queue of sent-message notifies for the queue. */ 151 | LIST_ENTRY NotifyMessagesListHead; 152 | /* Queue for hardware messages for the queue. */ 153 | LIST_ENTRY HardwareMessagesListHead; 154 | ... 155 | /* messages that are currently dispatched by other threads */ 156 | LIST_ENTRY DispatchingMessagesHead; 157 | /* messages that are currently dispatched by this message queue, required for cleanup */ 158 | LIST_ENTRY LocalDispatchingMessagesHead; 159 | ... 160 | } 161 | ``` 162 | 163 | ## 消息的接收 164 | 165 | 创建窗口就是在0环创建_WINDOW_OBJECT结构体,然后赋值。 166 | 167 | ![image-20230308204349224](./10消息机制/image-20230308204349224.png) 168 | 169 | ### GetMessage 170 | 171 | 从消息队列中取出消息 172 | 173 | ```c 174 | BOOL WINAPI GetMessage( 175 | LPMSG lpMsg, //返回从队列中取出的消息 176 | HWND hWnd, //过滤条件一:窗口句柄 177 | UINT wMsgFilterMin, //过滤条件二:最小值 178 | UINT wMsgFilterMax //过滤条件三:最大值 179 | ); 180 | ``` 181 | 182 | **主要功能**:循环判断是否存在属于该窗口的消息,若存在,则将消息存储到MSG指定的结构中,并将消息从列表中删除。 183 | 184 | 示例程序: 185 | 186 | ```c 187 | #include 188 | 189 | LRESULT CALLBACK WindowProc( 190 | IN HWND hwnd, 191 | IN UINT uMsg, 192 | IN WPARAM wParam, 193 | IN LPARAM lParam 194 | ){ 195 | switch(uMsg) 196 | { 197 | case 0x401: 198 | MessageBoxA(NULL, "测试窗口接收到消息", "新消息", MB_OK); 199 | return false; 200 | } 201 | 202 | return DefWindowProc(hwnd, uMsg, wParam, lParam); 203 | } 204 | 205 | 206 | int APIENTRY WinMain( 207 | HINSTANCE hInstance, 208 | HINSTANCE hPrevInstance, 209 | LPSTR lpCmdLine, 210 | int nShowCmd 211 | ){ 212 | //窗口的类名 213 | TCHAR className[] = "My First Window"; 214 | 215 | //创建一个自己的窗口 216 | WNDCLASS wndclass = {0}; 217 | wndclass.hbrBackground = (HBRUSH)COLOR_MENU; 218 | wndclass.lpfnWndProc = WindowProc; 219 | wndclass.lpszClassName = className; 220 | wndclass.hInstance = hInstance; 221 | 222 | //注册 223 | RegisterClass(&wndclass); 224 | 225 | //创建窗口 226 | HWND hwnd = CreateWindow( 227 | className, 228 | TEXT("测试窗口"), 229 | WS_OVERLAPPEDWINDOW, 230 | 10, 231 | 10, 232 | 600, 233 | 300, 234 | NULL, 235 | NULL, 236 | hInstance, 237 | NULL); 238 | 239 | if(hwnd == NULL) 240 | return 0; 241 | 242 | //显示窗口 243 | ShowWindow(hwnd, SW_SHOW); 244 | 245 | //消息循环 246 | MSG msg; 247 | while(GetMessage(&msg, NULL, 0, 0)) 248 | { 249 | //TranslateMessage(&msg); 250 | //DispatchMessage(&msg); 251 | } 252 | return 0; 253 | } 254 | ``` 255 | 256 | 不关闭该程序,运行: 257 | 258 | ```c 259 | #include 260 | #include 261 | 262 | int main() 263 | { 264 | HWND hwnd = FindWindow("My First Window", "测试窗口"); 265 | SendMessage(hwnd, 0x401, 0, 0); 266 | 267 | return 0; 268 | } 269 | ``` 270 | 271 | ### 同步与异步 272 | 273 | 1. 同步 274 | `SendMessage()`发送消息,`GetMessage()`接收,进入0环要遍历`SentMessagesListHead`有没有消息,有就处理,没有就返回,必须要处理完才会返回结果,`SendMessage()`要接收到结果才会结束否则会一直 堵塞在这 275 | 276 | 2. 异步 277 | `PostMessage()`发送消息,`GetMessage()`只会接收它的消息,不会处理,它的消息由`TranslateMessage(&msg)`与`DispatchMessage(&msg)来`处理 278 | 279 | `PostMessage()`发送完后是不会等待你的处理结果的,发完立马就结束 280 | 281 | 可以将上面的程序中改为:`PostMessage(hwnd, 0x401, 0, 0);`,可以看到上面的程序并没有处理消息。 282 | 283 | ## 消息的分发 284 | 285 | `GetMessage`能够处理`SentMessagesListHead`队列中的消息,其他队列中的消息则由`DispatchMessage`进行分发处理。 286 | 287 | **大致流程**: 288 | 289 | 1. 根据**窗口句柄**找到**窗口对象**。 290 | 2. 根据窗口对象得到**窗口过程函数**,由**0环**进行调用。 291 | 292 | ### DispatchMessage 293 | 294 | 用于消息分发,根据窗口句柄调用相关的窗口过程,通常用于分发由`GetMessage`函数检索到的消息。 295 | 296 | ```c 297 | LRESULT DispatchMessage( 298 | CONST MSG *lpmsg // message information 299 | ); 300 | ``` 301 | 302 | 示例代码: 303 | 304 | ```c 305 | #include 306 | #include 307 | 308 | LRESULT CALLBACK WindowProc( 309 | IN HWND hwnd, 310 | IN UINT uMsg, 311 | IN WPARAM wParam, 312 | IN LPARAM lParam 313 | ){ 314 | 315 | switch(uMsg) 316 | { 317 | case 0x401: 318 | { 319 | MessageBoxA(NULL, "测试窗口接收到消息", "新消息", MB_OK); 320 | return 0; 321 | } 322 | case WM_DESTROY: 323 | { 324 | ExitProcess(0); 325 | return 0; 326 | } 327 | } 328 | return DefWindowProc(hwnd, uMsg, wParam, lParam); 329 | } 330 | 331 | 332 | int APIENTRY WinMain( 333 | HINSTANCE hInstance, 334 | HINSTANCE hPrevInstance, 335 | LPSTR lpCmdLine, 336 | int nShowCmd 337 | ){ 338 | //窗口的类名 339 | TCHAR className[] = "My First Window"; 340 | 341 | //创建一个自己的窗口 342 | WNDCLASS wndclass = {0}; 343 | wndclass.hbrBackground = (HBRUSH)COLOR_MENU; 344 | wndclass.lpfnWndProc = WindowProc; 345 | wndclass.lpszClassName = className; 346 | wndclass.hInstance = hInstance; 347 | 348 | //注册 349 | RegisterClass(&wndclass); 350 | 351 | //创建窗口 352 | HWND hwnd = CreateWindow( 353 | className, 354 | TEXT("测试窗口"), 355 | WS_OVERLAPPEDWINDOW, 356 | 10, 357 | 10, 358 | 600, 359 | 300, 360 | NULL, 361 | NULL, 362 | hInstance, 363 | NULL); 364 | 365 | if(hwnd == NULL) 366 | return 0; 367 | 368 | //显示窗口 369 | ShowWindow(hwnd, SW_SHOW); 370 | 371 | //消息循环 372 | MSG msg; 373 | while(GetMessage(&msg, NULL, 0, 0)) 374 | { 375 | //TranslateMessage(&msg); 376 | //DispatchMessage(&msg); 377 | } 378 | 379 | return 0; 380 | } 381 | ``` 382 | 383 | 拖动窗口、点击最小化、缩放、关闭按钮均**无反应**;将`DispatchMessage`的注释去掉,可以得到响应。 384 | 385 | ### TranslateMessage 386 | 387 | 用于将虚拟键码转换为字符消息。该字符消息又被发送给对应线程(调用`TranslateMessage`的线程)的消息队列,当线程再次调用`GetMessage`函数或`PeekMessage`函数获取消息的时候被读取。 388 | 389 | 390 | 391 | ## 总结 392 | 393 | - `GetMessage`的不止能够取出消息,还能够处理消息。 394 | - `GetMessage`处理消息时,从0环回到3环调用窗口过程函数进行处理。 395 | - `SendMessage`发送消息后会等待目标处理完毕,`PostMessage`不会。 396 | - `GetMessage`只会处理`SentMessagesListHead`列表中的消息。 397 | - `DispatchMessage`的作用是分发除了`SentMessagesListHead`队列以外的消息给各窗口对象进行处理。 398 | - `TranslateMessage`只处理键盘消息,将虚拟键码转换为字符消息,再由`DispatchMessage`进行分发。 399 | - 未经过`TranslateMessage`处理的键盘消息,虚拟键码由`WM_KEYDOWN`进行处理;经过`TranslateMessage`处理的键盘消息,字符消息由`WM_CHAR`进行处理 400 | 401 | 402 | 403 | # 4.内核回调机制 404 | 405 | 406 | 407 | ## KeUserModeCallback 408 | 409 | 1)从0环调用3环函数的几种方式: 410 | 411 | - APC 412 | 413 | - 异常 414 | - 内核回调 415 | 416 | APC与异常回三环的落脚点比较单一,而消息机制需要处理的情况较多,不能使用同一个逻辑进行处理,因此消息机制使用内核回调调用三环函数。 417 | 418 | 2)回到3环的落脚点: 419 | 420 | - APC:`ntdll!KiUserApcDispatcher` 421 | 422 | - 异常:`ntdll!KiUserExceptionDispatcher` 423 | 424 | 3)内核回调在3环的落脚点:`KeUserModeCallback` 425 | 426 | > PEB+0x2C指向回调函数地址表。 427 | 428 | 4)凡是有窗口的程序就有可能0环直接调用3环的程序。 429 | 430 | ## 在OD中查看回调函数地址表 431 | 432 | 随便找个程序,找TEB: 433 | 434 | ![image-20230308211449772](./10消息机制/image-20230308211449772.png) 435 | 436 | 找PEB:在TEB+0x30的位置,+2C的位置就是回调地址表: 437 | 438 | ![image-20230308211547780](./10消息机制/image-20230308211547780.png) 439 | 440 | 可以看到: 441 | 442 | ![image-20230308211627411](./10消息机制/image-20230308211627411.png) 443 | 444 | 445 | 446 | 447 | 448 | ## 总结 449 | 450 | - 不是所有消息都是在进入消息循环后由`GetMessage`和`DispatchMessage`进行处理的,部分内核代码也能够调用窗口处理函数。 451 | - 内核代码通过`KeUserModeCallback`调用窗口处理函数,由第一个参数`FunctionID`决定回到三环时的落脚点。 452 | - `FunctionID`的值为回调地址表的索引,回调地址表位于`PEB+0x2C`位置,每个值为一个函数地址。 453 | -------------------------------------------------------------------------------- /10消息机制/image-20230304145550736.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/10消息机制/image-20230304145550736.png -------------------------------------------------------------------------------- /10消息机制/image-20230308204349224.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/10消息机制/image-20230308204349224.png -------------------------------------------------------------------------------- /10消息机制/image-20230308211449772.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/10消息机制/image-20230308211449772.png -------------------------------------------------------------------------------- /10消息机制/image-20230308211547780.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/10消息机制/image-20230308211547780.png -------------------------------------------------------------------------------- /10消息机制/image-20230308211627411.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/10消息机制/image-20230308211627411.png -------------------------------------------------------------------------------- /11.软件调试/image-20230308214733381.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/11.软件调试/image-20230308214733381.png -------------------------------------------------------------------------------- /11.软件调试/image-20230309191507860.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/11.软件调试/image-20230309191507860.png -------------------------------------------------------------------------------- /11.软件调试/image-20230310163025978.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/11.软件调试/image-20230310163025978.png -------------------------------------------------------------------------------- /11.软件调试/image-20230310163210216.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/11.软件调试/image-20230310163210216.png -------------------------------------------------------------------------------- /11.软件调试/image-20230310163423081.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/11.软件调试/image-20230310163423081.png -------------------------------------------------------------------------------- /11.软件调试/image-20230311110109036.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/11.软件调试/image-20230311110109036.png -------------------------------------------------------------------------------- /11.软件调试/image-20230311110308508.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/11.软件调试/image-20230311110308508.png -------------------------------------------------------------------------------- /11.软件调试/image-20230311111044990.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/11.软件调试/image-20230311111044990.png -------------------------------------------------------------------------------- /11.软件调试/image-20230311111147695.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/11.软件调试/image-20230311111147695.png -------------------------------------------------------------------------------- /11.软件调试/image-20230311111507666.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/11.软件调试/image-20230311111507666.png -------------------------------------------------------------------------------- /11.软件调试/image-20230311111947844.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/11.软件调试/image-20230311111947844.png -------------------------------------------------------------------------------- /11.软件调试/image-20230311112041778.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/11.软件调试/image-20230311112041778.png -------------------------------------------------------------------------------- /11.软件调试/image-20230311121728853.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/11.软件调试/image-20230311121728853.png -------------------------------------------------------------------------------- /11.软件调试/image-20230311230028195.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/11.软件调试/image-20230311230028195.png -------------------------------------------------------------------------------- /11.软件调试/image-20230312115603417.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/11.软件调试/image-20230312115603417.png -------------------------------------------------------------------------------- /11.软件调试/image-20230312120730668.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostasky/WinKernel/38076431babc9711186345f8803dbbe4ab560237/11.软件调试/image-20230312120730668.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WinKernel 2 | 3 | 滴水内核的课程笔记。 4 | 5 | 大致内容已完成,待更新细节部分。 6 | 7 | 欢迎star:smile: 8 | 9 | 目录: 10 | 11 | - 保护模式:[保护模式](https://github.com/Ghostasky/WinKernel/blob/main/01%E4%BF%9D%E6%8A%A4%E6%A8%A1%E5%BC%8F.md) 12 | - 驱动开发:[驱动开发](https://github.com/Ghostasky/WinKernel/blob/main/02%E9%A9%B1%E5%8A%A8.md) 13 | - 系统调用:[系统调用](https://github.com/Ghostasky/WinKernel/blob/main/03%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8.md) 14 | - 进程与线程:[进程与线程](https://github.com/Ghostasky/WinKernel/blob/main/04%E8%BF%9B%E7%A8%8B%E4%B8%8E%E7%BA%BF%E7%A8%8B.md) 15 | - 句柄表:[句柄表](https://github.com/Ghostasky/WinKernel/blob/main/05%E5%8F%A5%E6%9F%84%E8%A1%A8.md) 16 | - 事件等待:[事件等待](https://github.com/Ghostasky/WinKernel/blob/main/06%E4%BA%8B%E4%BB%B6%E7%AD%89%E5%BE%85.md) 17 | - APC机制:[APC机制](https://github.com/Ghostasky/WinKernel/blob/main/07APC%E6%9C%BA%E5%88%B6.md) 18 | - 异常:[异常](https://github.com/Ghostasky/WinKernel/blob/main/08%E5%BC%82%E5%B8%B8.md) 19 | - 内存管理:[内存管理](https://github.com/Ghostasky/WinKernel/blob/main/09%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.md) 20 | - 消息机制:[消息机制](https://github.com/Ghostasky/WinKernel/blob/main/10%E6%B6%88%E6%81%AF%E6%9C%BA%E5%88%B6.md) 21 | - 软件调试:[软件调试](https://github.com/Ghostasky/WinKernel/blob/main/11.%E8%BD%AF%E4%BB%B6%E8%B0%83%E8%AF%95.md) 22 | 23 | --------------------------------------------------------------------------------