动态库注入方式锁分析

This commit is contained in:
machunyu 2022-11-20 16:15:29 +08:00
parent d40a0fdb3d
commit 1491ef3061
4 changed files with 82 additions and 22 deletions

View File

@ -57,7 +57,7 @@
"description": "%deadlockdetect.taskDefinitions.options.cwd.description%"
},
"env": {
"type": "array",
"type": "object",
"description": "%deadlockdetect.taskDefinitions.options.env.description%"
}
}

View File

@ -1,17 +1,23 @@
import * as vscode from 'vscode';
import * as child from 'child_process';
import {execDetect, testPwd, prase_yaml2html} from './utils';
import {execDetect, archs, testPwd, prase_yaml2html} from './utils';
import { dirname, join } from 'path';
import { kill } from 'process';
import * as fs from 'fs';
type Options = {
cwd?: string;
env?: string[];
env?: {
[name: string]: any;
};
};
var isNotSupport = false;
const arch = archs.get(process.arch);
const binLoader: string = join(dirname(__dirname), "detect-tools/bincheck_loader.sh");
const hijackLib: string = join(dirname(__dirname), "detect-tools", arch? arch : "x86_64", "");
const hijackTool: string = join(dirname(__dirname), "detect-tools", arch? arch : "x86_64", "");
interface DetectTaskDefinition extends vscode.TaskDefinition {
command: string;
@ -19,14 +25,15 @@ interface DetectTaskDefinition extends vscode.TaskDefinition {
options?: Options;
}
export class DetectTaskProvider implements vscode.TaskProvider {
static customBuildScriptType = 'deadlockdetect';
private tasks: vscode.Task[] | undefined;
private sharedState: string | undefined;
private cmd: child.ChildProcessWithoutNullStreams | undefined;
constructor(private workspaceRoot: string, private context: vscode.ExtensionContext) { }
constructor(private workspaceRoot: string, private context: vscode.ExtensionContext, private _isNotSupport: boolean) {
isNotSupport = this._isNotSupport;
}
public async provideTasks(): Promise<vscode.Task[]> {
return this.getTasks();
@ -47,7 +54,6 @@ export class DetectTaskProvider implements vscode.TaskProvider {
}
this.tasks = [];
var option: Options = {
env: ["程序执行所需额外环境变量:如 DISPALY=1"],
};
this.tasks!.push(this.getTask("被检测可执行程序", ["可执行程序参数(可选)"], option));
return this.tasks;
@ -77,16 +83,16 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal {
onDidClose?: vscode.Event<number> = this.closeEmitter.event;
private passwd: string | undefined;
private checkedPid: number = 0;
private hadChecked: boolean = false;
constructor(private cmd: child.ChildProcessWithoutNullStreams | undefined, private context: vscode.ExtensionContext, private command: string, private args: string[], private option: Options, private getSharedState: () => string | undefined, private setSharedState: (state: string) => void) {
}
open(initialDimensions: vscode.TerminalDimensions | undefined): void {
// At this point we can start using the terminal.
if (this.command.length) {
let found = false;
vscode.workspace.workspaceFolders?.forEach((value)=>{
// value.uri.fsPath
if(this.command[0] == '/' && !found){
if(this.command[0] === '/' && !found){
this.option.cwd = value.uri.fsPath;
found = true;
}
@ -131,10 +137,35 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal {
this.closeEmitter.fire(0);
}
}
private hijackCheck(){
// 注入方式
child.exec(`${hijackTool} ${this.checkedPid}`, (err, o, e)=>{
if(o.match(/normal/)?.length){
const webPanel = vscode.window.createWebviewPanel(
'detectResultWebview',
"检测结果",
vscode.ViewColumn.One,
{
enableScripts: true,
retainContextWhenHidden: true,
}
);
webPanel.webview.html = prase_yaml2html(this.command, this.context.extensionPath, webPanel.webview, o);
return;
}
vscode.window.showInformationMessage("未检测到相关锁信息");
});
}
close(): void {
if(this.cmd){
kill(this.checkedPid, 9);
vscode.window.showWarningMessage("检测任务已退出");
if(isNotSupport && !this.hadChecked){
this.hadChecked = true;
this.hijackCheck();
}
}
}
@ -142,13 +173,18 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal {
private async doExec(): Promise<void> {
return new Promise<void>((resolve) => {
this.writeEmitter.fire('正在检测 ...\r\n');
this.option.env?.forEach(e =>{
let kv = e.split('=', 2);
if(kv.length === 2){
process.env[kv[0]] = kv[1];
}
if(this.option.env){
Object.keys(this.option.env).forEach(key => {
let value = this.option.env?.[key];
process.env[key] = value;
});
}
let hadPid = false;
if(isNotSupport){
// 库注入
this.hadChecked = false;
process.env["LD_PRELOAD"] = hijackLib;
}
let coption: child.SpawnOptionsWithoutStdio = {
env: process.env
};
@ -180,6 +216,11 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal {
if(errmsg.length){
vscode.window.showErrorMessage(errmsg);
}
if(errmsg.length === 0 && isNotSupport && !this.hadChecked){
// 注入后锁分析
this.hadChecked = true;
this.hijackCheck();
}
this.writeEmitter.fire('被检测程序已终止 ... \r\n');
const date = new Date();
this.setSharedState(date.toTimeString() + ' ' + date.toDateString());
@ -204,6 +245,10 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal {
if(result.length >= 4){
hadPid = true;
this.checkedPid = parseInt(result[3].trim());
if(isNotSupport){
// 注入方式
return;
}
execDetect(this.passwd, result[1].trim(), this.checkedPid, (detectResult)=>{
if(detectResult.match(/fatal/)?.length){
kill(this.checkedPid, 9);

View File

@ -5,7 +5,7 @@ import path = require('path');
import fs = require("fs");
import {DetectTaskProvider} from './detectTaskProvider';
import { homedir } from 'os';
import {exec} from 'child_process';
import {exec, execSync} from 'child_process';
import {testPwd} from './utils';
import {doLocalPidLockAnalyse} from './analysePid';
// linux命令操作模块
@ -157,13 +157,27 @@ export function activate(context: vscode.ExtensionContext) {
vscode.window.showWarningMessage("检测环境失败, C/C++程序锁分析插件功能受限");
return;
}
exec(`grep -r "^CONFIG_BPF_EVENTS=" /boot/config-${o}`, (e1, o1, err1)=>{
if(e1){
vscode.window.showWarningMessage("由于内核限制, C/C++程序锁分析插件功能受限");
return;
var kernelOptions: string[] = [
"CONFIG_UPROBES=y",
"CONFIG_UPROBE_EVENTS=y",
"CONFIG_TRACEPOINTS=y",
"CONFIG_PERF_EVENTS=y",
"CONFIG_BPF_EVENTS=y"
];
var isNotSupport = false;
fs.readFile(`/boot/config-${o}`, 'utf8', function (err, buffer) {
if(err){
isNotSupport = true;
}else{
var str = buffer.toString();
kernelOptions.forEach(elem=>{
if(!str.includes(elem)){
isNotSupport = true;
}
});
}
const workspaceRoot = (vscode.workspace.workspaceFolders && (vscode.workspace.workspaceFolders.length > 0)) ? vscode.workspace.workspaceFolders[0].uri.fsPath : homedir();
detectTaskProvider = vscode.tasks.registerTaskProvider(DetectTaskProvider.customBuildScriptType, new DetectTaskProvider(workspaceRoot, context));
detectTaskProvider = vscode.tasks.registerTaskProvider(DetectTaskProvider.customBuildScriptType, new DetectTaskProvider(workspaceRoot, context, isNotSupport));
});
});
context.subscriptions.push(...[disposable,disposable0]);

View File

@ -3,10 +3,11 @@ import * as vscode from 'vscode';
import { dirname, join } from 'path';
import * as YAML from 'yaml';
const archs = new Map([
export const archs = new Map([
["x86_64", "x86_64"],
["x64", "x86_64"],
["arm64", "arm64"]
["arm64", "arm64"],
["aarch64", "arm64"]
]);
const myArch = archs.get(process.arch);