enable syntax highlighting

This commit is contained in:
Joel Beckmeyer 2024-07-05 15:20:58 -04:00
parent 9c3d6a8748
commit b6922dcbd9
2 changed files with 33 additions and 16 deletions

View File

@ -30,8 +30,19 @@ enableGitInfo = true
[markup] [markup]
[markup.highlight] [markup.highlight]
anchorLineNos = false
codeFences = true codeFences = true
noClasses = false guessSyntax = true
hl_Lines = ''
hl_inline = false
lineAnchors = ''
lineNoStart = 1
lineNos = false
lineNumbersInTable = true
noClasses = true
noHl = false
style = "gruvbox"
tabWidth = 4
[markup.tableOfContents] [markup.tableOfContents]
startLevel = 1 startLevel = 1

View File

@ -7,7 +7,7 @@ draft: false
I've been wanting to get the AT&T visual voicemail "protocol" (ADVVM) working I've been wanting to get the AT&T visual voicemail "protocol" (ADVVM) working
in the LineageOS dialer. I thought I had made a breakthrough with the discovery in the LineageOS dialer. I thought I had made a breakthrough with the discovery
of the prefix in front of the VVM mail server address: of the prefix in front of the VVM mail server address:
``` ```url
srv=2:vvm.mobile.att.net srv=2:vvm.mobile.att.net
``` ```
[Another user raised an issue pointing to the same [Another user raised an issue pointing to the same
@ -21,7 +21,7 @@ STATUS SMS.
This brings us to the subject of the mysterious data SMS coming in on port 5499 This brings us to the subject of the mysterious data SMS coming in on port 5499
that I have wondered about ever since I discovered them in the logs when first that I have wondered about ever since I discovered them in the logs when first
"implementing" ADVVM. They can be triggered by sending a message of this format: "implementing" ADVVM. They can be triggered by sending a message of this format:
``` ```url
GET?c=ATTV:<device name>/<android short version>:<app version>&v=1.0&l=<10-digit phone number>&AD GET?c=ATTV:<device name>/<android short version>:<app version>&v=1.0&l=<10-digit phone number>&AD
``` ```
These SMS seemingly contain everything *useful* that the STATUS SMS contains, These SMS seemingly contain everything *useful* that the STATUS SMS contains,
@ -54,7 +54,7 @@ how?
Our dictionary is self-contained in an upper 4-bit prefix. Let's focus on the Our dictionary is self-contained in an upper 4-bit prefix. Let's focus on the
bottom four bits (or [nibble](https://en.wikipedia.org/wiki/Nibble)) by bottom four bits (or [nibble](https://en.wikipedia.org/wiki/Nibble)) by
removing the upper bits: removing the upper bits:
``` ```python
def get_stripped(text): def get_stripped(text):
return [ord(c) & 0x0f for c in text] return [ord(c) & 0x0f for c in text]
``` ```
@ -70,7 +70,7 @@ Duh! XOR is a reversible, non-destructive operator that [works great for
ciphering](https://en.m.wikipedia.org/wiki/XOR_cipher). ciphering](https://en.m.wikipedia.org/wiki/XOR_cipher).
Let's try it: Let's try it:
``` ```python
def xor_cipher(cipher, secret): def xor_cipher(cipher, secret):
if isinstance(cipher[0], str): if isinstance(cipher[0], str):
cipher = get_stripped(cipher) cipher = get_stripped(cipher)
@ -92,13 +92,13 @@ Well, this doesn't quite work. When run with the ciphertext and phone number,
it doesn't output the plaintext password that I am expecting. Not to worry, it doesn't output the plaintext password that I am expecting. Not to worry,
because we can also use the plaintext instead of the actual secret to gain some because we can also use the plaintext instead of the actual secret to gain some
insight. Below is the one with my throwaway number: insight. Below is the one with my throwaway number:
``` ```python
xor_cipher("[VW^QW\\W_X0", "00000000000") xor_cipher("[VW^QW\\W_X0", "00000000000")
[11, 6, 7, 14, 1, 7, 12, 7, 15, 8, 0] [11, 6, 7, 14, 1, 7, 12, 7, 15, 8, 0]
``` ```
The output of this is different for my throwaway and my actual phone number. So The output of this is different for my throwaway and my actual phone number. So
there is a unique 10-digit secret. Let's try a two-step decode: there is a unique 10-digit secret. Let's try a two-step decode:
``` ```python
first_pass = ''.join(chr(i) for i in xor_cipher("[VW^QW\\W_X0", "7345839476")) first_pass = ''.join(chr(i) for i in xor_cipher("[VW^QW\\W_X0", "7345839476"))
xor_cipher(first_pass, "00000000000") xor_cipher(first_pass, "00000000000")
[12, 5, 3, 11, 9, 4, 5, 3, 8, 14, 0] [12, 5, 3, 11, 9, 4, 5, 3, 8, 14, 0]
@ -107,11 +107,11 @@ xor_cipher(first_pass, "00000000000")
Now this is interesting! The output of this is the same for both of my phone Now this is interesting! The output of this is the same for both of my phone
lines. Additionally, it is identical to the output from my initial decode lines. Additionally, it is identical to the output from my initial decode
above. I think we've found a secondary secret, meaning the algorithm is: above. I think we've found a secondary secret, meaning the algorithm is:
``` ```pseudocode
secret XOR phonenumber XOR plaintext = ciphertext secret XOR phonenumber XOR plaintext = ciphertext
``` ```
Let's verify: Let's verify:
``` ```python
def decode(cipher, phonenumber): def decode(cipher, phonenumber):
secret = [12, 5, 3, 11, 9, 4, 5, 3, 8, 14] secret = [12, 5, 3, 11, 9, 4, 5, 3, 8, 14]
@ -127,7 +127,7 @@ Beatiful! This yields the same result for both phone numbers. Our secret is
[12, 5, 3, 11, 9, 4, 5, 3, 8, 14]. [12, 5, 3, 11, 9, 4, 5, 3, 8, 14].
Let's validate this more completely: Let's validate this more completely:
``` ```python
lookup_table = [ lookup_table = [
['[', 'V', 'W', '^', 'Q', 'W', '\\', 'W', '_', 'X'], ['[', 'V', 'W', '^', 'Q', 'W', '\\', 'W', '_', 'X'],
['Z', 'W', 'V', '_', 'P', 'V', ']', 'V', '^', 'Y'], ['Z', 'W', 'V', '_', 'P', 'V', ']', 'V', '^', 'Y'],
@ -151,6 +151,8 @@ def validate_decode(table, phone):
print(f'Success! decode("{ciphertext}", ...) == "{plaintext}"') print(f'Success! decode("{ciphertext}", ...) == "{plaintext}"')
validate_decode(lookup_table, "7345839476") validate_decode(lookup_table, "7345839476")
```
```stdout
Success! decode("[VW^QW\W_X", ...) == "0000000000" Success! decode("[VW^QW\W_X", ...) == "0000000000"
Success! decode("ZWV_PV]V^Y", ...) == "1111111111" Success! decode("ZWV_PV]V^Y", ...) == "1111111111"
Success! decode("YTU\SU^U]Z", ...) == "2222222222" Success! decode("YTU\SU^U]Z", ...) == "2222222222"
@ -170,7 +172,7 @@ that there is already some documentation on this ciphering, so I took a look.
Unfortunately, it looks like the cipher method has changed as this does not Unfortunately, it looks like the cipher method has changed as this does not
work for me. I verified that the number and lookup table do not work with my work for me. I verified that the number and lookup table do not work with my
decode as well: decode as well:
``` ```python
kop316_lookup_table = [ kop316_lookup_table = [
[ 'X', 'T', 'Q', '^', 'Z', 'S', 'U', 'U', '_', 'Y' ], [ 'X', 'T', 'Q', '^', 'Z', 'S', 'U', 'U', '_', 'Y' ],
[ 'Y', 'U', 'P', '_', '[', 'R', 'T', 'T', '^', 'X' ], [ 'Y', 'U', 'P', '_', '[', 'R', 'T', 'T', '^', 'X' ],
@ -184,6 +186,8 @@ kop316_lookup_table = [
[ 'Q', ']', 'X', 'W', 'S', 'Z', '\\', '\\', 'V', 'P' ], [ 'Q', ']', 'X', 'W', 'S', 'Z', '\\', '\\', 'V', 'P' ],
] ]
validate_decode(kop316_lookup_table, "2065550100") validate_decode(kop316_lookup_table, "2065550100")
```
```stdout
Failed on "6140620777" != decode("XTQ^ZSUU_Y", ...) Failed on "6140620777" != decode("XTQ^ZSUU_Y", ...)
Failed on "7051731666" != decode("YUP_[RTT^X", ...) Failed on "7051731666" != decode("YUP_[RTT^X", ...)
Failed on "4362402555" != decode("ZVS\XQWW][", ...) Failed on "4362402555" != decode("ZVS\XQWW][", ...)
@ -196,7 +200,7 @@ Failed on "14912814108151515" != decode("P\YVR[]]WQ", ...)
Failed on "15813915119141414" != decode("Q]XWSZ\\VP", ...) Failed on "15813915119141414" != decode("Q]XWSZ\\VP", ...)
``` ```
I also tried solving with both of these alternatives instead with no luck: I also tried solving with both of these alternatives instead with no luck:
``` ```pseudocode
secret XOR plaintext = ciphertext secret XOR plaintext = ciphertext
phonenumber XOR plaintext = ciphertext phonenumber XOR plaintext = ciphertext
``` ```
@ -204,17 +208,17 @@ But neither worked.
There is a secret that works for decoding this, and we can find it by following There is a secret that works for decoding this, and we can find it by following
the same method from above, using the fact that the same method from above, using the fact that
``` ```pseudocode
ciphertext XOR plaintext = secret ciphertext XOR plaintext = secret
``` ```
Let's try: Let's try:
``` ```python
xor_cipher("XTQ^ZSUU_Y", "0000000000") xor_cipher("XTQ^ZSUU_Y", "0000000000")
[8, 4, 1, 14, 10, 3, 5, 5, 15, 9] [8, 4, 1, 14, 10, 3, 5, 5, 15, 9]
``` ```
And then validating it: And then validating it:
``` ```python
kop316_lookup_table = [ kop316_lookup_table = [
["X", "T", "Q", "^", "Z", "S", "U", "U", "_", "Y"], ["X", "T", "Q", "^", "Z", "S", "U", "U", "_", "Y"],
["Y", "U", "P", "_", "[", "R", "T", "T", "^", "X"], ["Y", "U", "P", "_", "[", "R", "T", "T", "^", "X"],
@ -245,6 +249,8 @@ def validate_old_decode(table):
print(f'Success! decode("{ciphertext}", ...) == "{plaintext}"') print(f'Success! decode("{ciphertext}", ...) == "{plaintext}"')
validate_old_decode(kop316_lookup_table) validate_old_decode(kop316_lookup_table)
```
```stdout
Success! decode("XTQ^ZSUU_Y", ...) == "0000000000" Success! decode("XTQ^ZSUU_Y", ...) == "0000000000"
Success! decode("YUP_[RTT^X", ...) == "1111111111" Success! decode("YUP_[RTT^X", ...) == "1111111111"
Success! decode("ZVS\XQWW][", ...) == "2222222222" Success! decode("ZVS\XQWW][", ...) == "2222222222"