Skip to content

Commit

Permalink
Set up automatic code formatting using Prettier
Browse files Browse the repository at this point in the history
  • Loading branch information
niklashigi committed Jan 3, 2021
1 parent 185aee9 commit f358935
Show file tree
Hide file tree
Showing 16 changed files with 264 additions and 182 deletions.
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/node_modules
/dist
6 changes: 6 additions & 0 deletions .prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
semi: false,
trailingComma: 'all',
singleQuote: true,
arrowParens: 'avoid',
}
14 changes: 14 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"[typescript]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[markdown]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,15 @@ MIT © [Niklas Higi](https://shroudedcode.com)
[certificate-pinning]: https://owasp.org/www-community/controls/Certificate_and_Public_Key_Pinning#what-is-pinning
[manifest-debuggable]: https://developer.android.com/guide/topics/manifest/application-element#debug
[patch-certificate-pinning]: https://mobile-security.gitbook.io/mobile-security-testing-guide/android-testing-guide/0x05c-reverse-engineering-and-tampering#patching-example-disabling-certificate-pinning

[node]: https://nodejs.org/en/download/
[java]: https://www.oracle.com/technetwork/java/javase/downloads/index.html

[google-maps-android]: https://console.cloud.google.com/google/maps-apis/apis/maps-android-backend.googleapis.com
[google-api-key-restrictions]: https://cloud.google.com/docs/authentication/api-keys#api_key_restrictions
[android-app-bundle]: https://developer.android.com/platform/technology/app-bundle/
[apkpure]: https://apkpure.com/
[sai]: https://github.com/Aefyr/SAI

[charles]: https://www.charlesproxy.com/
[mitmproxy]: https://mitmproxy.org/

[apktool]: https://ibotpeaches.github.io/Apktool/
[apktool-issues]: https://github.com/iBotPeaches/Apktool/issues
[uber-apk-signer]: https://github.com/patrickfav/uber-apk-signer
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"scripts": {
"build": "tsc",
"test": "tsc",
"watch": "tsc --watch"
"watch": "tsc --watch",
"format": "prettier --write ."
},
"bin": "bin/apk-mitm",
"files": [
Expand Down Expand Up @@ -45,6 +46,7 @@
"@types/listr": "^0.14.2",
"@types/node": "14.14.10",
"@types/yargs-parser": "^15.0.0",
"prettier": "^2.2.1",
"typescript": "^4.1.2"
}
}
113 changes: 65 additions & 48 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ import UberApkSigner from './tools/uber-apk-signer'
import Tool from './tools/tool'

export type TaskOptions = {
inputPath: string,
outputPath: string,
apktool: Apktool,
uberApkSigner: UberApkSigner,
tmpDir: string,
wait: boolean,
inputPath: string
outputPath: string
apktool: Apktool
uberApkSigner: UberApkSigner
tmpDir: string
wait: boolean
}

interface PatchingError extends Error {
Expand Down Expand Up @@ -49,7 +49,8 @@ async function main() {
const inputPath = path.resolve(process.cwd(), input)

const fileExtension = path.extname(input)
const outputName = `${path.basename(input, fileExtension)}-patched${fileExtension}`
const baseName = path.basename(input, fileExtension)
const outputName = `${baseName}-patched${fileExtension}`
const outputPath = path.resolve(path.dirname(inputPath), outputName)

let taskFunction: (options: TaskOptions) => Listr
Expand Down Expand Up @@ -81,33 +82,43 @@ async function main() {
showVersions({ apktool, uberApkSigner })
console.log(chalk.dim(` Using temporary directory:\n ${tmpDir}\n`))

taskFunction({ inputPath, outputPath, tmpDir, apktool, uberApkSigner, wait: args.wait }).run().then(context => {
if (taskFunction === patchApk && context.usesAppBundle) {
showAppBundleWarning()
}

console.log(
chalk`\n {green.inverse Done! } Patched file: {bold ./${outputName}}\n`,
)
}).catch((error: PatchingError) => {
const message = getErrorMessage(error, { tmpDir })

console.error(
[
'',
chalk` {red.inverse.bold Failed! } An error occurred:`,
'',
message,
'',
` The full logs of all commands are available here:`,
` ${path.join(tmpDir, 'logs')}`,
''
].join('\n'),
)
if (process.arch.startsWith('arm')) showArmWarning()

process.exit(1)
taskFunction({
inputPath,
outputPath,
tmpDir,
apktool,
uberApkSigner,
wait: args.wait,
})
.run()
.then(context => {
if (taskFunction === patchApk && context.usesAppBundle) {
showAppBundleWarning()
}

console.log(
chalk`\n {green.inverse Done! } Patched file: {bold ./${outputName}}\n`,
)
})
.catch((error: PatchingError) => {
const message = getErrorMessage(error, { tmpDir })

console.error(
[
'',
chalk` {red.inverse.bold Failed! } An error occurred:`,
'',
message,
'',
` The full logs of all commands are available here:`,
` ${path.join(tmpDir, 'logs')}`,
'',
].join('\n'),
)
if (process.arch.startsWith('arm')) showArmWarning()

process.exit(1)
})
}

function getErrorMessage(error: PatchingError, { tmpDir }: { tmpDir: string }) {
Expand All @@ -116,18 +127,20 @@ function getErrorMessage(error: PatchingError, { tmpDir }: { tmpDir: string }) {
}

function formatCommandError(error: string, { tmpDir }: { tmpDir: string }) {
return error
// Replace mentions of the (sometimes very long) temporary directory path
.replace(new RegExp(tmpDir, 'g'), chalk`{bold <tmp_dir>}`)
// Highlight (usually relevant) warning lines in Apktool output
.replace(/^W: .+$/gm, line => chalk`{yellow ${line}}`)
// De-emphasize Apktool info lines
.replace(/^I: .+$/gm, line => chalk`{dim ${line}}`)
// De-emphasize (not very helpful) Apktool "could not exec" error message
.replace(
/^.+brut\.common\.BrutException: could not exec.+$/gm,
line => chalk`{dim ${line}}`
)
return (
error
// Replace mentions of the (sometimes very long) temporary directory path
.replace(new RegExp(tmpDir, 'g'), chalk`{bold <tmp_dir>}`)
// Highlight (usually relevant) warning lines in Apktool output
.replace(/^W: .+$/gm, line => chalk`{yellow ${line}}`)
// De-emphasize Apktool info lines
.replace(/^I: .+$/gm, line => chalk`{dim ${line}}`)
// De-emphasize (not very helpful) Apktool "could not exec" error message
.replace(
/^.+brut\.common\.BrutException: could not exec.+$/gm,
line => chalk`{dim ${line}}`,
)
)
}

function showHelp() {
Expand All @@ -148,9 +161,13 @@ function showSupportedExtensions() {
process.exit(1)
}

function showVersions(
{ apktool, uberApkSigner }: { apktool: Tool, uberApkSigner: Tool },
) {
function showVersions({
apktool,
uberApkSigner,
}: {
apktool: Tool
uberApkSigner: Tool
}) {
console.log(chalk`
{dim ╭} {blue {bold apk-mitm} v${version}}
{dim ├ {bold apktool} ${apktool.version.name}
Expand Down
67 changes: 39 additions & 28 deletions src/patch-apk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ import observeAsync from './utils/observe-async'

export default function patchApk(taskOptions: TaskOptions) {
const {
inputPath, outputPath, tmpDir, apktool, uberApkSigner, wait,
inputPath,
outputPath,
tmpDir,
apktool,
uberApkSigner,
wait,
} = taskOptions

const decodeDir = path.join(tmpDir, 'decode')
Expand All @@ -32,7 +37,7 @@ export default function patchApk(taskOptions: TaskOptions) {
},
{
title: 'Modifying app manifest',
task: async (context) => {
task: async context => {
const result = await modifyManifest(
path.join(decodeDir, 'AndroidManifest.xml'),
)
Expand All @@ -42,9 +47,10 @@ export default function patchApk(taskOptions: TaskOptions) {
},
{
title: 'Replacing network security config',
task: () => createNetworkSecurityConfig(
path.join(decodeDir, `res/xml/nsc_mitm.xml`),
),
task: () =>
createNetworkSecurityConfig(
path.join(decodeDir, `res/xml/nsc_mitm.xml`),
),
},
{
title: 'Disabling certificate pinning',
Expand All @@ -53,48 +59,53 @@ export default function patchApk(taskOptions: TaskOptions) {
{
title: 'Waiting for you to make changes',
enabled: () => wait,
task: () => observeAsync(async next => {
process.stdin.setEncoding('utf-8')
process.stdin.setRawMode(true)
task: () =>
observeAsync(async next => {
process.stdin.setEncoding('utf-8')
process.stdin.setRawMode(true)

next('Press any key to continue.')
await once(process.stdin, 'data')
next('Press any key to continue.')
await once(process.stdin, 'data')

process.stdin.setRawMode(false)
process.stdin.pause()
})
process.stdin.setRawMode(false)
process.stdin.pause()
}),
},
{
title: 'Encoding patched APK file',
task: () =>
new Listr([
{
title: 'Encoding using AAPT2',
task: (_, task) => observeAsync(async next => {
try {
await apktool.encode(decodeDir, tmpApkPath, true).forEach(next)
} catch {
task.skip('Failed, falling back to AAPT...')
fallBackToAapt = true
}
}),
task: (_, task) =>
observeAsync(async next => {
try {
await apktool
.encode(decodeDir, tmpApkPath, true)
.forEach(next)
} catch {
task.skip('Failed, falling back to AAPT...')
fallBackToAapt = true
}
}),
},
{
title: chalk`Encoding using AAPT {dim [fallback]}`,
skip: () => !fallBackToAapt,
task: () => apktool.encode(decodeDir, tmpApkPath, false),
},
])
]),
},
{
title: 'Signing patched APK file',
task: () => observeAsync(async next => {
await uberApkSigner
.sign([tmpApkPath], { zipalign: true })
.forEach(line => next(line))
task: () =>
observeAsync(async next => {
await uberApkSigner
.sign([tmpApkPath], { zipalign: true })
.forEach(line => next(line))

await fs.copyFile(tmpApkPath, outputPath)
}),
await fs.copyFile(tmpApkPath, outputPath)
}),
},
])
}
Expand Down
Loading

0 comments on commit f358935

Please sign in to comment.