1
0
Fork
You've already forked com.code49.crm
0
Reverse engineering at com.code49.crm APK
  • Makefile 92.9%
  • Nix 7.1%
Find a file
thisago a5c8cfa917 docs(readme): clean
I won't contine exploring this further as it may bring legal concerns.
2025年12月28日 12:48:28 +00:00
tools feat(makefile): hermes-dec 2025年12月26日 01:51:59 +00:00
.gitignore chore: remove npm dependencies 2025年12月26日 02:19:44 +00:00
.gitmodules feat(makefile): hermes-dec 2025年12月26日 01:51:59 +00:00
Makefile chore: remove npm dependencies 2025年12月26日 02:19:44 +00:00
README.org docs(readme): clean 2025年12月28日 12:48:28 +00:00
shell.nix feat(makefile): fetch, decompile, find things 2025年12月26日 01:07:35 +00:00

Reverse engineering at com.code49.crm APK

Makefile summary

make help
Targets:
 help - Shows available targets
 base.apk - Fetches the APK
 sources - Decompiles APK with jadx
 apkleaks.json - Looks for URLs and secrets with apkleaks
 tools/hermes-dec/build/ - Setup hermes-dec tool
 disassembled.hasm - Disassembles React Native Hermes bytecode bundle into annotated form
 decompiled.js - Decompiles React Native Hermes bytecode bundle into a pseudo JS code
 clean - Deletes all generated files

Researches

apkleaks.json

No meaningful data, except an Google API key.

disassembled.hasm

Grepping

Paths

grep -E "String: '/.{3,}' \(String\)" disassembled.hasm
==> 000000c4: <LoadConstString>: <Reg8: 4, string_id: 1974> # String: '/crm/api/auth/login' (String)
==> 000000e0: <LoadConstString>: <Reg8: 10, string_id: 1981> # String: '/crm/p.php' (String)
==> 0000010d: <LoadConstString>: <Reg8: 6, string_id: 673> # String: '/crm/api/device/validate' (String)

URLs

grep -E "String: 'https?://.+' \(String\)" disassembled.hasm
echo "Alternated match without protocol"
grep -Ei "String: '([a-z-]+\.)?[^ ]+\.(com(\.br)?|net|org).*' \(String\)" disassembled.hasm
==> 00000221: <LoadConstString>: <Reg8: 8, string_id: 3824> # String: 'https://classic-assets.eascdn.net/~assets/' (String)
==> 00000014: <LoadConstString>: <Reg8: 4, string_id: 3074> # String: 'https://e' (String)
==> 0000017c: <LoadConstString>: <Reg8: 1, string_id: 3831> # String: 'https://code49.net/api/app/report/error' (String)
==> 00000119: <LoadConstString>: <Reg8: 1, string_id: 2219> # String: 'http://localhost' (String)
==> 00000303: <LoadConstString>: <Reg8: 5, string_id: 3831> # String: 'https://code49.net/api/app/report/error' (String)
==> 00000133: <LoadConstString>: <Reg8: 1, string_id: 4484> # String: 'https://exp.host/--/api/v2/' (String)
==> 000000fa: <LoadConstString>: <Reg8: 1, string_id: 4485> # String: 'https://exp.host/--/api/v2/push/updateDeviceToken' (String)
Alternated match without protocol
==> 00000221: <LoadConstString>: <Reg8: 8, string_id: 3824> # String: 'https://classic-assets.eascdn.net/~assets/' (String)
==> 0000017c: <LoadConstString>: <Reg8: 1, string_id: 3831> # String: 'https://code49.net/api/app/report/error' (String)
==> 00000029: <LoadConstString>: <Reg8: 2, string_id: 2998> # String: 'social-media.code49.com' (String)
==> 00000303: <LoadConstString>: <Reg8: 5, string_id: 3831> # String: 'https://code49.net/api/app/report/error' (String)

Too much results

grep -Ei "String: '[^ ]*[a-z0-9]-[a-z0-9][^ ]*' \(String\)" disassembled.hasm

UUIDs

grep -Ei "String: '([0-9a-z]+-){4}([0-9a-z]+)' \(String\)" disassembled.hasm
==> 00000000: <LoadConstString>: <Reg8: 3, string_id: 1446> # String: 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' (String)
==> 0000002d: <LoadConstString>: <Reg8: 3, string_id: 2028> # String: '6ba7b810-9dad-11d1-80b4-00c04fd430c8' (String)
==> 00000037: <LoadConstString>: <Reg8: 3, string_id: 2030> # String: '6ba7b811-9dad-11d1-80b4-00c04fd430c8' (String)
==> 00000041: <LoadConstString>: <Reg8: 3, string_id: 2031> # String: '6ba7b812-9dad-11d1-80b4-00c04fd430c8' (String)
==> 0000004b: <LoadConstString>: <Reg8: 3, string_id: 2032> # String: '6ba7b814-9dad-11d1-80b4-00c04fd430c8' (String)

Publisher name

grep -Ei "code49" disassembled.hasm
==> 0000017c: <LoadConstString>: <Reg8: 1, string_id: 3831> # String: 'https://code49.net/api/app/report/error' (String)
==> 00000029: <LoadConstString>: <Reg8: 2, string_id: 2998> # String: 'social-media.code49.com' (String)
==> 00000303: <LoadConstString>: <Reg8: 5, string_id: 3831> # String: 'https://code49.net/api/app/report/error' (String)

decompiled.js

Grepping

Paths

grep -E '"/.{3,}" decompiled.js

sources/resources/res/values/strings.xml

sed '136q;d' sources/resources/res/values/strings.xml
 <string name="google_storage_bucket">crm-49-app.appspot.com</string>

sources/resources/com.code49.crm.apk/assets/app.config

jq -r '.extra.eas.projectId' <sources/resources/com.code49.crm.apk/assets/app.config
3c7d5e97-a83e-4b5a-8c39-8060134973b8

Findings about APIs

POST /crm/api/auth/login

Body:

  • username
  • password
  • client = "app"
  • device

Reference:

sed -n '303046,303067 p' decompiled.js
case 156:
 r4 = _closure1_slot6;
 r8 = r4.default;
 r7 = r8.post;
 r10 = r6;
 r12 = r10.url;
 r4 = global;
 r4 = r4.HermesInternal;
 r11 = r4.concat;
 r5 = '';
 r4 = '/crm/api/auth/login';
 r5 = r11.bind(r5)(r12, r4);
 r4 = {};
 r11 = r10.username;
 r4['username'] = r11;
 r10 = r10.password;
 r4['password'] = r10;
 r10 = 'app';
 r4['client'] = r10;
 r4['device'] = r9;
 r4 = r7.bind(r8)(r5, r4);
 SaveGenerator(address=254);

Host

I suppose the r4 = r4.HermesInternal; is some kind of env handling.