Skip to content

Commit

Permalink
Prevent permission error in Linux when getting viber auth data
Browse files Browse the repository at this point in the history
  • Loading branch information
laggykiller committed Jun 10, 2024
1 parent 03c639e commit f2b31ce
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 18 deletions.
2 changes: 1 addition & 1 deletion src/sticker_convert/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ def get_opt_cred(self, args: Namespace) -> CredOption:
)

if args.viber_get_auth:
get_viber_auth = GetViberAuth()
get_viber_auth = GetViberAuth(self.cb.ask_str)

viber_bin_path = None
if args.viber_bin_path:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
GUIUtils.finalize_window(self)

def cb_get_cred(self) -> None:
m = GetViberAuth()
m = GetViberAuth(self.cb_ask_str_viber)

viber_bin_path = None
if self.gui.viber_bin_path_var.get():
Expand All @@ -123,7 +123,7 @@ def cb_get_cred(self) -> None:
self.cb_msg_block_viber(msg)

def cb_launch_viber(self) -> None:
m = GetViberAuth()
m = GetViberAuth(self.cb_ask_str_viber)
viber_bin_path = m.get_viber_desktop()

if self.gui.viber_auth_var.get():
Expand Down
26 changes: 26 additions & 0 deletions src/sticker_convert/resources/memdump.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash
# Reference: https://github.com/hajzer/bash-memory-dump

OS_PAGESIZE=`getconf PAGESIZE`

PID=$1
PID_MAPS=/proc/$PID/maps
PID_MEM=/proc/$PID/mem

rm -f /tmp/viber.dmp.$PID
grep rw-p $PID_MAPS |
while IFS='' read -r line || [[ -n "$line" ]]; do
range=`echo $line | awk '{print $1;}'`

vma_start=$(( 0x`echo $range | cut -d- -f1` ))
vma_end=$(( 0x`echo $range | cut -d- -f2` ))
vma_size=$(( $vma_end - $vma_start ))

dd_start=$(( $vma_start / $OS_PAGESIZE ))
dd_bs=$OS_PAGESIZE
dd_count=$(( $vma_size / $OS_PAGESIZE ))

set +e
dd if="$PID_MEM" bs="$dd_bs" skip="$dd_start" count="$dd_count"
set -e
done
138 changes: 123 additions & 15 deletions src/sticker_convert/utils/auth/get_viber_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
import shutil
import subprocess
import time
from getpass import getpass
from pathlib import Path
from typing import Optional, Tuple, cast
from typing import Callable, Optional, Tuple, cast

from sticker_convert.definitions import ROOT_DIR

# psutil is missing on arm64 linux appimage
# Note: There is no Viber Desktop on arm64 linux anyway
Expand Down Expand Up @@ -40,33 +43,46 @@ def killall(name: str) -> bool:
result = False

for proc in psutil.process_iter(): # type: ignore
if proc.name() == name:
if name in proc.name().lower():
proc.kill()
result = True

return result


def find_pid_by_name(name: str) -> Optional[int]:
if not PSUTIL_LOADED:
return None

for proc in psutil.process_iter(): # type: ignore
if name in proc.name().lower():
return proc.pid

return None


class GetViberAuth:
def get_auth(self, viber_bin_path: str) -> Tuple[Optional[str], str]:
def __init__(self, cb_ask_str: Callable[..., str] = input):
self.cb_ask_str = cb_ask_str

def get_auth_windows(self, viber_bin_path: str) -> Tuple[Optional[str], str]:
if not PSUTIL_LOADED:
return None, MSG_NO_PSUTIL

member_id = None
m_token = None
m_ts = None

viber_process_name = Path(viber_bin_path).name.replace(".AppImage", "")

killed = killall(viber_process_name)
killed = killall("viber")
if killed:
time.sleep(5)
subprocess.Popen([viber_bin_path])
time.sleep(10)

from PyMemoryEditor import OpenProcess # type: ignore

with OpenProcess(process_name=viber_process_name) as process:
viber_pid = find_pid_by_name("viber")
with OpenProcess(pid=viber_pid) as process:
for address in process.search_by_value(str, 18, "X-Viber-Auth-Mid: "): # type: ignore
member_id_addr = cast(int, address) + 18
member_id_bytes = process.read_process_memory(member_id_addr, bytes, 20)
Expand All @@ -92,7 +108,93 @@ def get_auth(self, viber_bin_path: str) -> Tuple[Optional[str], str]:
if m_ts is None:
return None, MSG_NO_AUTH

killall(viber_process_name)
killall("viber")

viber_auth = f"member_id:{member_id};m_token:{m_token};m_ts:{m_ts}"
msg = "Got viber_auth successfully:\n"
msg += f"{viber_auth=}\n"

return viber_auth, msg

def get_auth_linux(self, viber_bin_path: str) -> Tuple[Optional[str], str]:
if not PSUTIL_LOADED:
return None, MSG_NO_PSUTIL

member_id = None
m_token = None
m_ts = None

killed = killall("viber")
if killed:
time.sleep(5)
subprocess.Popen([viber_bin_path])
time.sleep(10)

viber_pid = find_pid_by_name("viber")
memdump_sh_path = (ROOT_DIR / "resources/memdump.sh").as_posix()

s = subprocess.run(
[
memdump_sh_path,
str(viber_pid),
],
capture_output=True,
).stdout

if s.find(b"X-Viber-Auth-Mid: ") != -1:
pass
elif shutil.which("pkexec") and os.getenv("DISPLAY"):
s = subprocess.run(
[
"pkexec",
memdump_sh_path,
str(viber_pid),
],
capture_output=True,
).stdout
else:
prompt = "Enter sudo password: "
if self.cb_ask_str != input:
sudo_password = self.cb_ask_str(
prompt, initialvalue="", cli_show_initialvalue=False
)
else:
sudo_password = getpass(prompt)
sudo_password_pipe = subprocess.Popen(
("echo", sudo_password), stdout=subprocess.PIPE
)
s = subprocess.run(
[
"sudo",
"-S",
memdump_sh_path,
str(viber_pid),
],
capture_output=True,
stdin=sudo_password_pipe.stdout,
).stdout

member_id_addr = s.find(b"X-Viber-Auth-Mid: ")
m_token_addr = s.find(b"X-Viber-Auth-Token: ")
m_ts_addr = s.find(b"X-Viber-Auth-Timestamp: ")

if member_id_addr == -1 or m_token_addr == -1 or m_ts_addr == -1:
return None, MSG_NO_AUTH

member_id_addr += 18
m_token_addr += 20
m_ts_addr += 24

member_id_bytes = s[member_id_addr : member_id_addr + 20]
member_id_term = member_id_bytes.find(b"\x0d\x0a")
if member_id_term == -1:
return None, MSG_NO_AUTH
member_id = member_id_bytes[:member_id_term].decode(encoding="ascii")

m_token = s[m_token_addr : m_token_addr + 64].decode(encoding="ascii")
m_ts = s[m_ts_addr : m_ts_addr + 13].decode(encoding="ascii")

killall("viber")

viber_auth = f"member_id:{member_id};m_token:{m_token};m_ts:{m_ts}"
msg = "Got viber_auth successfully:\n"
Expand All @@ -112,7 +214,7 @@ def get_auth_darwin(self, viber_bin_path: str) -> Tuple[Optional[str], str]:
if "enabled" in csrutil_status:
return None, MSG_SIP_ENABLED

killed = killall("Viber")
killed = killall("viber")
if killed:
time.sleep(5)
subprocess.run(
Expand Down Expand Up @@ -143,15 +245,19 @@ def get_auth_darwin(self, viber_bin_path: str) -> Tuple[Optional[str], str]:
s = f.read()

os.remove("/tmp/viber.dmp")
killall("Viber")
killall("viber")

member_id_addr = s.find(b"X-Viber-Auth-Mid: ") + 18
m_token_addr = s.find(b"X-Viber-Auth-Token: ") + 20
m_ts_addr = s.find(b"X-Viber-Auth-Timestamp: ") + 24
member_id_addr = s.find(b"X-Viber-Auth-Mid: ")
m_token_addr = s.find(b"X-Viber-Auth-Token: ")
m_ts_addr = s.find(b"X-Viber-Auth-Timestamp: ")

if member_id_addr == -1 or m_token_addr == -1 or m_ts_addr == -1:
return None, MSG_NO_AUTH

member_id_addr += 18
m_token_addr += 20
m_ts_addr += 24

member_id_bytes = s[member_id_addr : member_id_addr + 20]
member_id_term = member_id_bytes.find(b"\x0d\x0a")
if member_id_term == -1:
Expand Down Expand Up @@ -201,7 +307,9 @@ def get_cred(
if not viber_bin_path:
return None, MSG_NO_BIN

if platform.system() == "Darwin":
if platform.system() == "Windows":
return self.get_auth_windows(viber_bin_path)
elif platform.system() == "Darwin":
return self.get_auth_darwin(viber_bin_path)
else:
return self.get_auth(viber_bin_path)
return self.get_auth_linux(viber_bin_path)

0 comments on commit f2b31ce

Please sign in to comment.