从安卓客户端的密钥数据库读取密钥 #24

Merged
lsr merged 7 commits from feat/import-from-android into main 2023-06-11 22:39:20 +00:00
10 changed files with 1110 additions and 1608 deletions
Showing only changes of commit dec7f86115 - Show all commits

View File

@ -31,10 +31,9 @@
"react-dom": "^18.2.0",
"react-dropzone": "^14.2.3",
"react-icons": "^4.9.0",
"react-markdown": "^8.0.7",
"react-promise-suspense": "^0.3.4",
"react-redux": "^8.0.5",
"remark-gfm": "^3.0.1",
"react-syntax-highlighter": "^15.5.0",
"sass": "^1.63.3",
"sql.js": "^1.8.0"
},
@ -46,6 +45,7 @@
"@types/node": "^20.2.5",
"@types/react": "^18.2.7",
"@types/react-dom": "^18.2.4",
"@types/react-syntax-highlighter": "^15.5.7",
"@types/sql.js": "^1.4.4",
"@types/testing-library__jest-dom": "^5.14.6",
"@typescript-eslint/eslint-plugin": "^5.59.7",

File diff suppressed because it is too large Load Diff

View File

@ -1,26 +0,0 @@
.markdown {
h3 {
font-weight: bold;
font-size: 1.25em;
}
h4 {
font-weight: bold;
font-size: 1.15em;
margin-top: 0.5em;
}
p,
pre {
margin-block-start: 1em;
margin-block-end: 1em;
margin-inline-start: 0px;
margin-inline-end: 0px;
}
pre {
white-space: pre-wrap;
padding-left: 0.5em;
border-left: 2px solid #ddd;
}
}

View File

@ -1,11 +0,0 @@
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import MarkdownContentClass from './MarkdownContent.module.scss';
export function MarkdownContent({ children }: { children: string }) {
return (
<div className={MarkdownContentClass.markdown}>
<ReactMarkdown remarkPlugins={[remarkGfm]}>{children}</ReactMarkdown>
</div>
);
}

View File

@ -1,23 +0,0 @@
### 安卓端获取密钥数据库
你可能需要 root 或类似的访问权限。绝大多数情况下,这会导致你的安卓设备失去保修资格。
#### 提取文件(文件浏览器)
1. 提升到 `root` 权限,访问 `/data/data/com.tencent.qqmusic/databases/` 目录,将文件 `player_process_db`
复制到正常模式下用户可访问的目录(如下载目录)。
2. 如果你需要在电脑上进行解密操作,请将该文件复制到电脑。
3. 选择该文件。
#### 提取文件ADB
※ 目前该指令只支持 Linux & Mac
1. 打开终端并安装好依赖,并复制下述指令:
```sh
adb shell su -c "cat '/data/data/com.tencent.qqmusic/databases/player_process_db' | gzip | base64" \
| base64 -d | gzip -d player_process_db
```
2. 选择提取的这个文件即可。

View File

@ -2,7 +2,6 @@ import {
Button,
Center,
Flex,
Heading,
Modal,
ModalBody,
ModalCloseButton,
@ -15,14 +14,16 @@ import {
TabPanel,
TabPanels,
Tabs,
useToast,
} from '@chakra-ui/react';
import { FileInput } from '~/components/FileInput';
import mdHelpAndroid from './DocAndroid.md?raw';
import { MarkdownContent } from '~/components/MarkdownContent';
import { qmc2ImportKeys } from '../../settingsSlice';
import { useAppDispatch } from '~/hooks';
import { DatabaseKeyExtractor } from '~/util/DatabaseKeyExtractor';
import { QMCv2AndroidInstructions } from './QMCv2AndroidInstructions';
export interface ImportFileModalProps {
show: boolean;
onClose: () => void;
@ -30,6 +31,7 @@ export interface ImportFileModalProps {
export function ImportFileModal({ onClose, show }: ImportFileModalProps) {
const dispatch = useAppDispatch();
const toast = useToast();
const handleFileReceived = async (files: File[]) => {
try {
const file = files[0];
@ -41,6 +43,13 @@ export function ImportFileModal({ onClose, show }: ImportFileModalProps) {
if (qmc2Keys) {
dispatch(qmc2ImportKeys(qmc2Keys));
onClose();
toast({
title: `导入成功 (${qmc2Keys.length})`,
description: '记得保存更改来应用。',
isClosable: true,
duration: 5000,
status: 'success',
});
return;
}
alert(`不是支持的 SQLite 数据库文件。\n表名${qmc2Keys}`);
@ -57,31 +66,27 @@ export function ImportFileModal({ onClose, show }: ImportFileModalProps) {
<Modal isOpen={show} onClose={onClose} scrollBehavior="inside" size="xl">
<ModalOverlay />
<ModalContent>
<ModalHeader></ModalHeader>
<ModalHeader></ModalHeader>
<ModalCloseButton />
<Flex as={ModalBody} gap={2} flexDir="column">
<Flex as={ModalBody} gap={2} flexDir="column" flex={1}>
<Center>
<FileInput onReceiveFiles={handleFileReceived}></FileInput>
</Center>
<Heading as="h2" size="md" mt="4">
使
</Heading>
<Tabs variant="enclosed">
<Flex as={Tabs} variant="enclosed" flexDir="column" mt={4} flex={1} minH={0}>
<TabList>
<Tab></Tab>
<Tab></Tab>
{/* <Tab>Two</Tab> */}
</TabList>
<TabPanels>
<TabPanels flex={1} overflow="auto">
<TabPanel>
<MarkdownContent>{mdHelpAndroid}</MarkdownContent>
<QMCv2AndroidInstructions />
</TabPanel>
<TabPanel>
<p>two!</p>
</TabPanel>
</TabPanels>
</Tabs>
</Flex>
</Flex>
<ModalFooter>

View File

@ -0,0 +1,113 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Box,
Heading,
Link,
ListItem,
OrderedList,
Text,
} from '@chakra-ui/react';
import { ExternalLinkIcon } from '@chakra-ui/icons';
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter';
import hljsStyleGitHub from 'react-syntax-highlighter/dist/esm/styles/hljs/github';
import PowerShellAdbDumpCommand from './adb_dump.ps1?raw';
import ShellAdbDumpCommand from './adb_dump.sh?raw';
export function QMCv2AndroidInstructions() {
return (
<>
<Text>
<code>root</code> 访
</Text>
<Text></Text>
<Accordion allowToggle mt="2">
<AccordionItem>
<Heading as="h3" size="md">
<AccordionButton>
<Box as="span" flex="1" textAlign="left">
</Box>
<AccordionIcon />
</AccordionButton>
</Heading>
<AccordionPanel pb={4}>
<OrderedList>
<ListItem>
使 <code>root</code> 访 <code>/data/data/com.tencent.qqmusic/databases/</code>
{' 目录,将文件 '}
<code>player_process_db</code> 访
</ListItem>
<ListItem></ListItem>
</OrderedList>
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<Heading as="h3" size="md">
<AccordionButton>
<Box as="span" flex="1" textAlign="left">
PC ADB / PowerShell
</Box>
<AccordionIcon />
</AccordionButton>
</Heading>
<AccordionPanel pb={4}>
<OrderedList>
<ListItem>
<code>adb</code>
<br />
💡
<Link href="https://scoop.sh/#/apps?q=adb" isExternal color="blue.600">
使 Scoop <ExternalLinkIcon />
</Link>
</ListItem>
<ListItem> PowerShell 7 </ListItem>
<ListItem></ListItem>
<ListItem>
<SyntaxHighlighter language="ps1" style={hljsStyleGitHub}>
{PowerShellAdbDumpCommand}
</SyntaxHighlighter>
</ListItem>
<ListItem>
<code>player_process_db</code>
</ListItem>
</OrderedList>
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<Heading as="h3" size="md">
<AccordionButton>
<Box as="span" flex="1" textAlign="left">
Linux / Mac ADB / Shell
</Box>
<AccordionIcon />
</AccordionButton>
</Heading>
<AccordionPanel pb={4}>
<OrderedList>
<ListItem></ListItem>
<ListItem>
<SyntaxHighlighter language="bash" style={hljsStyleGitHub}>
{ShellAdbDumpCommand}
</SyntaxHighlighter>
</ListItem>
<ListItem>
<code>player_process_db</code>
</ListItem>
</OrderedList>
</AccordionPanel>
</AccordionItem>
</Accordion>
</>
);
}

View File

@ -0,0 +1,11 @@
try {
$gz_b64 = adb shell su -c "cat '/data/data/com.tencent.qqmusic/databases/player_process_db' | gzip | base64" | Out-String
$bStream = New-Object System.IO.MemoryStream(,[System.Convert]::FromBase64String($gz_b64))
$decoded = New-Object System.IO.Compression.GzipStream($bStream, [System.IO.Compression.CompressionMode]::Decompress)
$outFile = New-Object System.IO.FileStream("player_process_db", [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write)
$decoded.CopyTo($outFile)
} finally {
if ($outFile -ne $null) { $outFile.Dispose() }
if ($decoded -ne $null) { $decoded.Dispose() }
if ($bStream -ne $null) { $bStream.Dispose() }
}

View File

@ -0,0 +1,2 @@
sh adb shell su -c "cat '/data/data/com.tencent.qqmusic/databases/player_process_db' | gzip | base64" \
| base64 -d | gzip -d player_process_db

View File

@ -3,6 +3,13 @@ import ReactDOM from 'react-dom/client';
import { AppRoot } from './components/AppRoot';
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter';
import hljsSyntaxPowerShell from 'react-syntax-highlighter/dist/esm/languages/hljs/powershell';
import hljsSyntaxBash from 'react-syntax-highlighter/dist/esm/languages/hljs/bash';
SyntaxHighlighter.registerLanguage('ps1', hljsSyntaxPowerShell);
SyntaxHighlighter.registerLanguage('bash', hljsSyntaxBash);
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<AppRoot />