Skip to content

Commit c8b5b19

Browse files
committed
feat: add console component for logging and integrate with deobfuscator output
1 parent 0fd1c80 commit c8b5b19

6 files changed

Lines changed: 377 additions & 101 deletions

File tree

packages/deob/src/index.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,28 @@ function handleError(error: any, rawCode: string) {
6161

6262
const logger = debug('Deob')
6363

64+
function shorten(value: string, max = 120) {
65+
const clean = value.replace(/\s+/g, ' ').trim()
66+
if (clean.length <= max)
67+
return clean
68+
return `${clean.slice(0, max)}...`
69+
}
70+
71+
function buildDecryptionSummaryLog(map: Map<string, string>) {
72+
const lines = []
73+
74+
lines.push(`- 解密条目: ${map.size} 个`)
75+
if (map.size) {
76+
const preview = Array.from(map.entries()).slice(0, 5)
77+
preview.forEach(([key, value]) => {
78+
lines.push(` • ${key} -> ${shorten(String(value))}`)
79+
})
80+
}
81+
82+
lines.push('====================')
83+
return lines.join('\n')
84+
}
85+
6486
export function evalCode(code: string) {
6587
try {
6688
const result = global.eval(code)
@@ -165,8 +187,7 @@ export class Deob {
165187
decoders = designDecoder(this.ast, options.designDecoderName!)
166188
}
167189

168-
logger(`${stringArray ? `字符串数组: ${stringArray?.name} 数组长度:${stringArray?.length}` : '没找到字符串数组'}`)
169-
logger(`${decoders.length ? `解密器: ${decoders.map(d => d.name)}` : '没找到解密器'}`)
190+
logger(`${stringArray ? `字符串数组: ${stringArray?.name}` : '没找到字符串数组'} | ${decoders.length ? `解密器函数: ${decoders.map(d => d.name)}` : '没找到解密器函数'}`)
170191

171192
evalCode(setupCode)
172193

@@ -182,7 +203,7 @@ export class Deob {
182203

183204
const map = decodeStrings(decoders)
184205

185-
logger('解密结果:', map)
206+
logger(buildDecryptionSummaryLog(map))
186207

187208
if (options.isRemoveDecoder && !options.isStrongRemove) {
188209
stringArray?.path.remove()

website/components/Console.vue

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
<script setup lang="ts">
2+
import { Pane } from 'splitpanes'
3+
import type { ConsoleLogEntry } from '~/types/logger'
4+
5+
const props = withDefaults(defineProps<{
6+
logs: ConsoleLogEntry[]
7+
size: number
8+
collapsed: boolean
9+
}>(), {
10+
logs: () => [],
11+
size: 24,
12+
collapsed: false,
13+
})
14+
15+
const emit = defineEmits<{
16+
(e: 'toggle'): void
17+
(e: 'clear'): void
18+
}>()
19+
20+
const logContainer = shallowRef<HTMLDivElement>()
21+
const timeFormatter = new Intl.DateTimeFormat('zh-CN', {
22+
hour12: false,
23+
hour: '2-digit',
24+
minute: '2-digit',
25+
second: '2-digit',
26+
})
27+
28+
function formatTime(value: number) {
29+
return timeFormatter.format(new Date(value))
30+
}
31+
32+
watch(
33+
() => props.logs.length,
34+
async () => {
35+
if (props.collapsed)
36+
return
37+
38+
await nextTick()
39+
const container = logContainer.value
40+
if (container)
41+
container.scrollTo({ top: container.scrollHeight })
42+
},
43+
)
44+
45+
watch(
46+
() => props.collapsed,
47+
async (collapsed) => {
48+
if (!collapsed) {
49+
await nextTick()
50+
const container = logContainer.value
51+
if (container)
52+
container.scrollTo({ top: container.scrollHeight })
53+
}
54+
},
55+
)
56+
</script>
57+
58+
<template>
59+
<Pane
60+
:size="size"
61+
:min-size="collapsed ? 0 : 10"
62+
class="min-h-0"
63+
>
64+
<div
65+
class="flex flex-col rounded-lg border border-zinc-200/80 bg-white/90 shadow-sm dark:(border-zinc-800/80 bg-zinc-950/60)" :class="[
66+
collapsed ? 'h-auto' : 'h-full',
67+
]"
68+
>
69+
<div class="flex items-center justify-between gap-3 border-b border-zinc-200/70 px-3 py-2 text-xs font-medium text-zinc-700 dark:(border-zinc-800/70 text-zinc-200)">
70+
<div class="flex items-center gap-2">
71+
<div class="i-ri:terminal-box-line text-lg text-amber-500" />
72+
<span class="font-semibold">控制台</span>
73+
<span class="text-[11px] font-normal text-zinc-500 dark:text-zinc-400">实时查看 Deob 日志</span>
74+
</div>
75+
<div class="flex items-center gap-2">
76+
<button
77+
v-if="logs.length"
78+
class="inline-flex items-center gap-1 rounded-md border border-zinc-200/70 bg-white/90 px-2 py-1 text-[11px] font-medium text-zinc-700 shadow-sm transition hover:(border-amber-400 text-amber-700) dark:(border-zinc-700 bg-zinc-900/80 text-zinc-200)"
79+
title="清空日志"
80+
@click="emit('clear')"
81+
>
82+
<div class="i-ri:delete-bin-6-line text-sm" />
83+
<span>清空</span>
84+
</button>
85+
<button
86+
class="inline-flex items-center gap-1 rounded-md border border-zinc-200/70 bg-white/90 px-2 py-1 text-[11px] font-medium text-zinc-700 shadow-sm transition hover:(border-amber-400 text-amber-700) dark:(border-zinc-700 bg-zinc-900/80 text-zinc-200)"
87+
title="展开或收起"
88+
@click="emit('toggle')"
89+
>
90+
<div :class="collapsed ? 'i-ri:layout-bottom-line' : 'i-ri:arrow-down-s-line'" class="text-sm" />
91+
<span>{{ collapsed ? '展开' : '收起' }}</span>
92+
</button>
93+
</div>
94+
</div>
95+
<div
96+
v-if="!collapsed"
97+
ref="logContainer"
98+
class="min-h-0 flex-1 overflow-auto rounded-b-lg bg-gradient-to-b from-zinc-950/70 via-zinc-950/80 to-black px-3 py-2 font-mono text-[12px] leading-6 text-zinc-100 shadow-inner dark:(from-zinc-950/80 via-zinc-900/80 to-black)"
99+
>
100+
<template v-if="logs.length">
101+
<div
102+
v-for="entry in logs"
103+
:key="entry.id"
104+
class="mb-2 last:mb-0 rounded-md bg-white/5 p-2 shadow-inner ring-1 ring-white/5"
105+
>
106+
<div class="text-[10px] uppercase tracking-wide text-emerald-400/80">
107+
{{ formatTime(entry.timestamp) }}
108+
</div>
109+
<pre class="mt-1 whitespace-pre-wrap break-words">{{ entry.message }}</pre>
110+
</div>
111+
</template>
112+
<div
113+
v-else
114+
class="flex h-full items-center justify-center text-xs text-zinc-500 dark:text-zinc-400"
115+
>
116+
运行解混淆后,这里会显示日志输出
117+
</div>
118+
</div>
119+
</div>
120+
</Pane>
121+
</template>

0 commit comments

Comments
 (0)