Список российских Android приложений для раздельного проксирования

Дисклеймер для особо умных и не особо внимательных: я в курсе, что уход от слежки Минцифры руками компаний требует комплексного подхода, и раздельное проксирование - лишь один из методов. Всё, что я делаю - делюсь списком, который смог нарыть и теперь применяю у себя как одну из мер противодействия. Не нравится - перейдите в другую тему. Спасибо.

На основе свежего исследования по тому, какие российские Android приложения уже сейчас ведут слежку за использованием VPN, был составлен список тех, кого надо пустить в обход. Уже несколько дней хотел собрать такой список, но какой-то готовой базы данных не было, а руками собирать лень.

Сам список:

com.avito.android
com.idamob.tinkoff.android
com.vk.vkvideo
com.vkontakte.android
com.wildberries.ru
com.yandex.browser
ru.alfabank.mobile.android
ru.beru.android
ru.dublgis.dgismobile
ru.foodfox.client
ru.kinopoisk
ru.mail.mailapp
ru.megafon.mlk
ru.megamarket.marketplace
ru.mts.mymts
ru.nspk.mirpay
ru.ok.android
ru.oneme.app
ru.ozon.app.android
ru.rostel
ru.rutube.app
ru.sbcs.store
ru.sberbankmobile
ru.vk.store
ru.vtb24.mobilebanking.android
ru.yandex.music
ru.yandex.taxi
ru.yandex.yandexmaps
ru.zen.android
com.uma.musicvk

Держите скрипт

https://ntc.party/t/методы-защиты-от-по-со-шпионскими-модулями-с-15042026/23825/238

Спасибо, очень полезно!

Яндекс маркет совершенно точно детектировал ВПН (писал на экране), по крайне мере при переходе в раздел с играми. Сейчас думаю начнет и в других разделах.

Нагаллюцинировал скрипт на основе трудов товарища выше:

package main

import (
	"context"
	"errors"
	"flag"
	"fmt"
	"html"
	"io"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"sync"
	"time"
)

const (
	defaultBaseURL   = "https://www.rustore.ru"
	defaultUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"
)

// Only developer IDs with public /catalog/developer/<id> pages are kept here.
// Some RuStore app pages expose only app-scoped "#dev" metadata, which is not enough for developer crawling.
var suspiciousSeedDeveloperIDs = []string{
	"25cb8eb5", // ООО "Иви.ру"
	"df91b73f", // VK
	"3x3cjaw2", // ALIEXPRESS CIS HOLDING PTE. LTD.
	"xashx42f", // MAX
	"9607cd14", // ООО «ИТ ИКС 5 Технологии»
	"mbtttt4v", // X5 Digital
	"78c1c8ed", // Перекрёсток
	"47fc945b", // Рестрим Медиа
	"d32f20ae", // ООО "ДубльГИС"
	"a5ce9c44", // ООО «Новые Туристические Технологии»
	"bc26d940", // ООО «Айриэлтор»
	"d91661ae", // ООО "Интернет Решения"
	"77a2530c", // Lamoda
	"63d0ea9f", // Лента
	"589be38f", // ООО "КЕХ еКоммерц"
	"100677d1", // ООО "ЛитРес"
	"a65961e0", // ПАО Сбербанк
	"c184ae7c", // ООО "ЯНДЕКС"
	"8f8f8250", // РАМБЛЕР ИНТЕРНЕТ ХОЛДИНГ
	"taavi9x0", // ООО "ИНФОМЕТЕОС"
	"55a9d1b1", // АО "Вкусвилл"
	"2c6a10fd", // ООО "Хэдхантер"
	"3smwwz3s", // Лемана ПРО
	"aabea2de", // ПАО "Магнит"
	"f384b98f", // ООО "РУФОРМ"
	"d57e19b3", // ООО "РИТМ Медиа"
	"35702095", // ООО "НСТ"
	"75883313", // АО "Телекомпания НТВ"
	"68416ebf", // ООО «НТВ-ПЛЮС»
	"8ccdebf0", // ООО "Фонбет ТВ"
	"63ea48cb", // ООО "Премьер"
	"e1d653c2", // ООО "ГПМ Радио"
	"a15900d5", // ООО "Оператор Газпром ИД"
	"18c4231b", // Okko LLC
	"0f7f523b", // НАО «Национальная спутниковая компания»
	"7a17e879", // ООО "Вайлдберриз"
	"d2ef9d4c", // ООО «ВсеИнструменты.ру»
	"b46d9f81", // Минцифры РФ
	"cb96cc4c", // АО «НСПК»
	"041fcfd1", // ОАО "РЖД"
	"b2730967", // ИАЦ в сфере здравоохранения города Москвы
	"cc01aebe", // ООО "Умное пространство"
	"fc3ecc0d", // АО «ТБанк»
	"31f09962", // АО «Россельхозбанк»
	"80e24324", // Банк ВТБ (ПАО)
	"a1243e95", // АО "Альфа-Банк"
	"9ddbb7d9", // Газпромбанк
	"f0f02d9b", // ПАО "Банк ПСБ"
	"lm5fnpob", // ПСБ Маркет
	"2b19ctbj", // CDEK Digital
	"9ef76af6", // ПАО «Ростелеком»
	"457798ab", // Пикабу
	"a1407e2c", // Почта России
	"94c9fae3", // ПАО МТС
	"25bd713d", // МегаФон
	"0e6451b5", // ПАО "ВымпелКом"
	"30001e4c", // ООО "Скартел"
	"07c20ddf", // ЭР-Телеком Холдинг
	"692ed825", // Центр развития перспективных технологий
	"2fc01da6", // Информационный город ГКУ
	"8c1fc8f1", // Дептранс Москвы
	"3a7b8579", // ООО "НОВЫЕ ОБЛАЧНЫЕ ТЕХНОЛОГИИ"
	"3022b99c", // ООО «Т2 Мобайл»
	"4ba404e1", // Оператор информационной системы
	"097f5ee0", // ООО "еАптека"
	"e955a92e", // Семейный доктор
	"5ff74c45", // YCLIENTS
	"d7ae51b3", // АО "Лаборатория Касперского"
	"pkktcyox", // ООО "Доктор Веб"
	"f0f99c7d", // ООО «М Тех»
	"5e533ced", // ДНС
	"3ac7c3c3", // ПАО "Аэрофлот"
	"42d293c2", // ООО "ФЛАУВАУ"
}

// Packages that exist in RuStore app pages but are not exposed through any public developer page we can crawl.
// They are added only if developer crawling did not already produce them.
var suspiciousDirectPackages = []string{
	"ru.plazius.cofix", // CofixGlobal (RuStore exposes only app-scoped #dev metadata)
}

var (
	appPairRe              = regexp.MustCompile(`"packageName":"((?:\\.|[^"\\])+)","appName":"((?:\\.|[^"\\])*)"`)
	appHrefRe              = regexp.MustCompile(`href="/catalog/app/([^"?#]+)"`)
	nextLinkHrefRe         = regexp.MustCompile(`<link rel="next" href="([^"]+)"`)
	nextAnchorHrefRe       = regexp.MustCompile(`<a[^>]*data-testid="next"[^>]*href="([^"]+)"`)
	nextAnchorHrefAltRe    = regexp.MustCompile(`<a[^>]*href="([^"]+)"[^>]*data-testid="next"`)
	pageH1Re               = regexp.MustCompile(`<h1[^>]*>([^<]+)</h1>`)
	appDeveloperAuthorIDRe = regexp.MustCompile(`author":\{"@id":"https://www\.rustore\.ru(/catalog/developer/[^"]+)"`)
	appDeveloperHrefRe     = regexp.MustCompile(`href="(/catalog/developer/[^"?#"]+)"`)
	appDeveloperOrgNameRe  = regexp.MustCompile(`\{"@type":"Organization","@id":"https://www\.rustore\.ru/catalog/developer/[^"]+"(?:,"url":"[^"]+")?,"name":"((?:\\.|[^"\\])+)"`)
	appScopedOrgNameRe     = regexp.MustCompile(`\{"@type":"Organization","@id":"https://www\.rustore\.ru/catalog/app/[^"]+#dev","name":"((?:\\.|[^"\\])+)"`)
)

type config struct {
	baseURL           string
	maxDeveloperPages int
	maxSeedDevelopers int
	concurrency       int
	timeout           time.Duration
	outputPath        string
	verbose           bool
}

type crawler struct {
	cfg    config
	client *http.Client
	ticker *time.Ticker

	cacheMu sync.Mutex
	cache   map[string]string
}

type appInfo struct {
	PackageName   string
	AppName       string
	DeveloperName string
	DeveloperPath string
}

type developerSeed struct {
	ID   string
	Path string
	Name string
}

type developerApps struct {
	Path string
	Name string
	Apps []appInfo
}

func main() {
	cfg := parseFlags()

	if err := run(cfg); err != nil {
		fmt.Fprintf(os.Stderr, "error: %v\n", err)
		os.Exit(1)
	}
}

func parseFlags() config {
	cfg := config{}

	flag.StringVar(&cfg.baseURL, "base-url", defaultBaseURL, "RuStore base URL")
	flag.IntVar(&cfg.maxDeveloperPages, "developer-pages", 0, "How many pages to read per developer (0 = all)")
	flag.IntVar(&cfg.maxSeedDevelopers, "max-seed-developers", 0, "Limit how many seed developers are crawled (0 = all)")
	flag.IntVar(&cfg.concurrency, "concurrency", 3, "Parallel requests for app and developer pages")
	flag.DurationVar(&cfg.timeout, "timeout", 20*time.Second, "HTTP timeout per request")
	flag.StringVar(&cfg.outputPath, "output", "", "Write results to this file instead of stdout")
	flag.BoolVar(&cfg.verbose, "v", false, "Print progress to stderr")
	flag.Parse()

	if cfg.concurrency < 1 {
		cfg.concurrency = 1
	}

	return cfg
}

func run(cfg config) error {
	ctx := context.Background()

	c := &crawler{
		cfg: cfg,
		client: &http.Client{
			Timeout: cfg.timeout,
		},
		ticker: time.NewTicker(300 * time.Millisecond),
		cache:  make(map[string]string),
	}
	defer c.ticker.Stop()

	developers, err := c.collectSeedDevelopers()
	if err != nil {
		return err
	}
	c.logf("seed developers discovered: %d", len(developers))

	if cfg.maxSeedDevelopers > 0 && len(developers) > cfg.maxSeedDevelopers {
		developers = developers[:cfg.maxSeedDevelopers]
	}
	c.logf("seed developers selected for crawling: %d", len(developers))

	directPackages, err := c.collectDirectSeedPackages()
	if err != nil {
		return err
	}
	c.logf("direct packages configured: %d", len(directPackages))

	finalApps := c.collectDeveloperApps(ctx, developers)
	if len(finalApps) == 0 {
		return fmt.Errorf("no apps collected from developer pages")
	}
	finalApps = c.mergeDirectPackages(ctx, finalApps, directPackages)

	lines := renderOutput(finalApps, developers)
	return writeOutput(cfg.outputPath, lines)
}

func (c *crawler) collectSeedDevelopers() ([]*developerSeed, error) {
	if len(suspiciousSeedDeveloperIDs) == 0 {
		return nil, fmt.Errorf("no suspicious seed developers configured")
	}

	seen := make(map[string]struct{}, len(suspiciousSeedDeveloperIDs))
	seeds := make([]*developerSeed, 0, len(suspiciousSeedDeveloperIDs))
	for _, id := range suspiciousSeedDeveloperIDs {
		id = cleanText(id)
		if id == "" {
			continue
		}
		if _, exists := seen[id]; exists {
			continue
		}
		seen[id] = struct{}{}
		seeds = append(seeds, &developerSeed{
			ID:   id,
			Path: "/catalog/developer/" + id,
		})
	}
	if len(seeds) == 0 {
		return nil, fmt.Errorf("no suspicious seed developers configured")
	}

	return seeds, nil
}

func (c *crawler) collectDirectSeedPackages() ([]string, error) {
	if len(suspiciousDirectPackages) == 0 {
		return nil, nil
	}

	seen := make(map[string]struct{}, len(suspiciousDirectPackages))
	packages := make([]string, 0, len(suspiciousDirectPackages))
	for _, pkg := range suspiciousDirectPackages {
		pkg = cleanText(pkg)
		if pkg == "" {
			continue
		}
		if _, exists := seen[pkg]; exists {
			continue
		}
		seen[pkg] = struct{}{}
		packages = append(packages, pkg)
	}

	return packages, nil
}

func (c *crawler) collectDeveloperApps(ctx context.Context, developers []*developerSeed) []appInfo {
	type result struct {
		seed *developerSeed
		data developerApps
		err  error
	}

	sort.Slice(developers, func(i, j int) bool {
		return developers[i].ID < developers[j].ID
	})

	jobs := make(chan *developerSeed)
	results := make(chan result)

	var wg sync.WaitGroup
	for i := 0; i < c.cfg.concurrency; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for seed := range jobs {
				data, err := c.crawlDeveloper(ctx, seed.Path)
				results <- result{seed: seed, data: data, err: err}
			}
		}()
	}

	go func() {
		for _, seed := range developers {
			jobs <- seed
		}
		close(jobs)
		wg.Wait()
		close(results)
	}()

	appsByPackage := make(map[string]appInfo)
	for res := range results {
		if res.err != nil {
			c.logf("skip developer crawl: %v", res.err)
			continue
		}

		if res.seed != nil {
			if res.seed.Name == "" && res.data.Name != "" {
				res.seed.Name = res.data.Name
			}
			c.logf("seed developer: %s | %s", res.seed.ID, coalesce(res.seed.Name, res.seed.Path))
		}

		for _, app := range res.data.Apps {
			current, exists := appsByPackage[app.PackageName]
			if !exists || betterAppInfo(app, current) {
				appsByPackage[app.PackageName] = app
			}
		}
	}

	out := make([]appInfo, 0, len(appsByPackage))
	for _, app := range appsByPackage {
		out = append(out, app)
	}

	return out
}

func (c *crawler) mergeDirectPackages(ctx context.Context, apps []appInfo, packages []string) []appInfo {
	if len(packages) == 0 {
		return apps
	}

	appsByPackage := make(map[string]appInfo, len(apps)+len(packages))
	for _, app := range apps {
		appsByPackage[app.PackageName] = app
	}

	for _, pkg := range packages {
		if _, exists := appsByPackage[pkg]; exists {
			c.logf("direct package already covered: %s", pkg)
			continue
		}

		app := appInfo{
			PackageName: pkg,
			AppName:     pkg,
		}

		body, err := c.fetch(ctx, c.absolute("/catalog/app/"+pkg))
		if err != nil {
			c.logf("direct package fetch failed: %s: %v", pkg, err)
		} else {
			app.AppName = coalesce(extractPageH1(body), pkg)
			app.DeveloperName = extractAppCompanyName(body)
			app.DeveloperPath = extractAppDeveloperPath(body)
		}

		appsByPackage[pkg] = app
		c.logf("direct package: %s | %s | %s", app.PackageName, coalesce(app.AppName, pkg), coalesce(app.DeveloperName, app.DeveloperPath, "direct-only"))
	}

	out := make([]appInfo, 0, len(appsByPackage))
	for _, app := range appsByPackage {
		out = append(out, app)
	}

	return out
}

func betterAppInfo(left, right appInfo) bool {
	if right.AppName == "" && left.AppName != "" {
		return true
	}
	if right.DeveloperName == "" && left.DeveloperName != "" {
		return true
	}
	return false
}

func (c *crawler) crawlDeveloper(ctx context.Context, path string) (developerApps, error) {
	fullURL := c.absolute(path)
	visited := make(map[string]struct{})
	current := fullURL
	pagesRead := 0

	apps := make(map[string]appInfo)
	developerName := ""

	for current != "" {
		if _, ok := visited[current]; ok {
			break
		}
		if c.cfg.maxDeveloperPages > 0 && pagesRead >= c.cfg.maxDeveloperPages {
			break
		}
		visited[current] = struct{}{}

		body, err := c.fetch(ctx, current)
		if err != nil {
			return developerApps{}, fmt.Errorf("fetch %s: %w", current, err)
		}

		if developerName == "" {
			developerName = extractDeveloperName(body)
		}

		for pkg, name := range extractApps(body) {
			app := apps[pkg]
			previous := app
			app.PackageName = pkg
			app.AppName = coalesce(app.AppName, name, pkg)
			app.DeveloperName = coalesce(app.DeveloperName, developerName)
			app.DeveloperPath = path
			apps[pkg] = app
			if previous.PackageName == "" || betterAppInfo(app, previous) {
				c.logf("collected app: %s | %s | %s", app.PackageName, coalesce(app.AppName, app.PackageName), coalesce(app.DeveloperName, path))
			}
		}

		current = extractNextURL(body, current)
		pagesRead++
	}

	out := make([]appInfo, 0, len(apps))
	for _, app := range apps {
		if app.DeveloperName == "" {
			app.DeveloperName = developerName
		}
		out = append(out, app)
	}

	sort.Slice(out, func(i, j int) bool {
		if out[i].AppName != out[j].AppName {
			return out[i].AppName < out[j].AppName
		}
		return out[i].PackageName < out[j].PackageName
	})

	return developerApps{
		Path: path,
		Name: developerName,
		Apps: out,
	}, nil
}

func renderOutput(apps []appInfo, developers []*developerSeed) []string {
	developersByPath := make(map[string]*developerSeed, len(developers))
	for _, dev := range developers {
		developersByPath[dev.Path] = dev
	}

	sort.Slice(apps, func(i, j int) bool {
		left := apps[i]
		right := apps[j]

		leftDeveloper := left.DeveloperName
		if leftDeveloper == "" && developersByPath[left.DeveloperPath] != nil {
			leftDeveloper = developersByPath[left.DeveloperPath].Name
		}
		rightDeveloper := right.DeveloperName
		if rightDeveloper == "" && developersByPath[right.DeveloperPath] != nil {
			rightDeveloper = developersByPath[right.DeveloperPath].Name
		}

		if leftDeveloper != rightDeveloper {
			return leftDeveloper < rightDeveloper
		}
		if left.AppName != right.AppName {
			return left.AppName < right.AppName
		}
		return left.PackageName < right.PackageName
	})

	lines := make([]string, 0, len(apps))
	for _, app := range apps {
		lines = append(lines, app.PackageName)
	}

	return lines
}

func writeOutput(outputPath string, lines []string) error {
	var w io.Writer = os.Stdout
	var file *os.File
	var err error

	if outputPath != "" {
		file, err = os.Create(outputPath)
		if err != nil {
			return fmt.Errorf("create output file: %w", err)
		}
		defer file.Close()
		w = file
	}

	for _, line := range lines {
		if _, err := fmt.Fprintln(w, line); err != nil {
			return fmt.Errorf("write output: %w", err)
		}
	}

	return nil
}

func (c *crawler) fetch(ctx context.Context, rawURL string) (string, error) {
	fullURL := c.absolute(rawURL)

	c.cacheMu.Lock()
	if body, ok := c.cache[fullURL]; ok {
		c.cacheMu.Unlock()
		return body, nil
	}
	c.cacheMu.Unlock()

	var lastErr error

	for attempt := 1; attempt <= 5; attempt++ {
		<-c.ticker.C

		req, err := http.NewRequestWithContext(ctx, http.MethodGet, fullURL, nil)
		if err != nil {
			return "", err
		}
		req.Header.Set("User-Agent", defaultUserAgent)
		req.Header.Set("Accept", "text/html,application/xhtml+xml")

		resp, err := c.client.Do(req)
		if err != nil {
			lastErr = err
			if attempt < 5 {
				time.Sleep(backoffDuration(attempt))
				continue
			}
			return "", err
		}

		data, readErr := io.ReadAll(resp.Body)
		resp.Body.Close()
		if readErr != nil {
			lastErr = readErr
			if attempt < 5 {
				time.Sleep(backoffDuration(attempt))
				continue
			}
			return "", readErr
		}

		body := string(data)
		if isRateLimited(resp.StatusCode, body) {
			lastErr = fmt.Errorf("rate limited on %s", fullURL)
			if attempt < 5 {
				time.Sleep(backoffDuration(attempt))
				continue
			}
			break
		}

		if resp.StatusCode != http.StatusOK {
			lastErr = fmt.Errorf("%s returned %s", fullURL, resp.Status)
			if shouldRetryStatus(resp.StatusCode) && attempt < 5 {
				time.Sleep(backoffDuration(attempt))
				continue
			}
			return "", lastErr
		}

		c.cacheMu.Lock()
		c.cache[fullURL] = body
		c.cacheMu.Unlock()

		return body, nil
	}

	if lastErr == nil {
		lastErr = errors.New("request failed")
	}
	return "", lastErr
}

func shouldRetryStatus(status int) bool {
	return status == http.StatusTooManyRequests || status >= 500
}

func isRateLimited(status int, body string) bool {
	if status == http.StatusTooManyRequests {
		return true
	}
	return strings.Contains(body, "Ошибка 429")
}

func backoffDuration(attempt int) time.Duration {
	if attempt < 1 {
		attempt = 1
	}
	return time.Duration(attempt*attempt) * time.Second
}

func extractApps(body string) map[string]string {
	apps := make(map[string]string)
	for _, match := range appPairRe.FindAllStringSubmatch(body, -1) {
		if len(match) != 3 {
			continue
		}
		pkg := decodeJSONFragment(match[1])
		name := decodeJSONFragment(match[2])
		if pkg == "" {
			continue
		}
		if _, exists := apps[pkg]; !exists {
			apps[pkg] = coalesce(name, pkg)
		}
	}
	for _, match := range appHrefRe.FindAllStringSubmatch(body, -1) {
		if len(match) != 2 {
			continue
		}
		pkg := cleanText(match[1])
		if pkg == "" {
			continue
		}
		if _, exists := apps[pkg]; !exists {
			apps[pkg] = pkg
		}
	}
	return apps
}

func extractNextURL(body, current string) string {
	for _, re := range []*regexp.Regexp{nextLinkHrefRe, nextAnchorHrefRe, nextAnchorHrefAltRe} {
		match := re.FindStringSubmatch(body)
		if len(match) == 2 {
			return resolveURL(current, html.UnescapeString(match[1]))
		}
	}
	return ""
}

func extractPageH1(body string) string {
	match := pageH1Re.FindStringSubmatch(body)
	if len(match) != 2 {
		return ""
	}
	return cleanText(match[1])
}

func extractDeveloperName(body string) string {
	return extractPageH1(body)
}

func extractAppDeveloperPath(body string) string {
	for _, re := range []*regexp.Regexp{appDeveloperAuthorIDRe, appDeveloperHrefRe} {
		match := re.FindStringSubmatch(body)
		if len(match) == 2 {
			return ensurePath(match[1])
		}
	}
	return ""
}

func extractAppCompanyName(body string) string {
	for _, re := range []*regexp.Regexp{appDeveloperOrgNameRe, appScopedOrgNameRe} {
		match := re.FindStringSubmatch(body)
		if len(match) == 2 {
			return cleanText(decodeJSONFragment(match[1]))
		}
	}
	return ""
}

func decodeJSONFragment(fragment string) string {
	if fragment == "" {
		return ""
	}

	decoded, err := strconv.Unquote(`"` + fragment + `"`)
	if err != nil {
		return html.UnescapeString(fragment)
	}
	return html.UnescapeString(decoded)
}

func cleanText(s string) string {
	return strings.TrimSpace(html.UnescapeString(s))
}

func resolveURL(baseURL, ref string) string {
	base, err := url.Parse(baseURL)
	if err != nil {
		return ref
	}
	next, err := url.Parse(ref)
	if err != nil {
		return ref
	}
	return base.ResolveReference(next).String()
}

func absoluteWithBase(base, raw string) string {
	if strings.HasPrefix(raw, "http://") || strings.HasPrefix(raw, "https://") {
		return raw
	}
	base = strings.TrimRight(base, "/")
	return base + ensurePath(raw)
}

func (c *crawler) absolute(raw string) string {
	return absoluteWithBase(c.cfg.baseURL, raw)
}

func ensurePath(raw string) string {
	if strings.HasPrefix(raw, "/") {
		return raw
	}
	return "/" + raw
}

func coalesce(values ...string) string {
	for _, value := range values {
		if strings.TrimSpace(value) != "" {
			return value
		}
	}
	return ""
}

func (c *crawler) logf(format string, args ...any) {
	if !c.cfg.verbose {
		return
	}
	fmt.Fprintf(os.Stderr, format+"\n", args...)
}

На данный момент собирает 463 приложения:

ru.aliexpress.buyer
com.logistic.sdek
ru.cdek.courier
ru.cdek.ek5
ru.plazius.cofix
com.lamoda.lite
ru.more.play
tv.okko.androidtv
com.BOGG.ART.VKT
com.allgoritm.youla
com.my.mygamesapp
com.uma.musicvk
com.vk.admin
com.vk.calls
com.vk.clips
com.vk.im
com.vk.love
com.vk.mail
com.vk.tv
com.vk.vkvideo
com.vkontakte.android
games.my.cloud
games.my.cloud.tv
live.vkplay.app
ru.mail.biz.avocado
ru.mail.cloud
ru.mail.horo.android
ru.mail.intranet
ru.mail.mailapp
ru.mail.my
ru.mail.search.electroscope
ru.ok.android
ru.ok.dating
ru.vk.hrtek
ru.zen.android
com.x5.courierapp
com.x5.pickerapp.ff
apps.yclients1
com.yclients.yplaces
ru.alfabank.mobile.android
ru.alfabank.oavdo.amc
ru.alfadirect.app
ru.lifepay.pos.alfapos
ru.m4bank.softpos.alfaru
com.vkusvill.courier
com.vkusvill.vacancy
ru.vkusvill
app.subscab.android
com.kaspersky.kes
com.kaspersky.passwordmanager
com.kaspersky.petka
com.kaspersky.safekids
com.kaspersky.secure.connection
com.kaspersky.who_calls
com.kms.free
ru.ntv.client
ru.ntv.client.tv
ru.ntv.today
ru.nspk.mir.loyalty
ru.nspk.mirpay
ru.nspk.sbpay
ru.intech.lki
ru.m4bank.softpos.rshb
ru.rshb.dbo
ru.rshb.dboul
ru.rshb.digitalCoworkerOffice
ru.rshb.ips_qr
ru.rshb.privatebusiness
ru.rshb.svoe_rodnoe
ru.rshb.svoedom_android
ru.rshb.svojfermer
ruagro.start.tech
com.idamob.tinkoff.android
com.journal_tj
com.uchebnik_tj
ru.tbank.myt
ru.tinkoff.bnpl
ru.tinkoff.investing
ru.tinkoff.lifestyle.fuel.sme
ru.tinkoff.mvno
ru.tinkoff.posterminal
ru.tinkoff.sme
az.vtb.android
com.horosho.tips
ru.lifepay.pos.vtb
ru.m4bank.softpos.vtbpos
ru.vtb.corporate.android.main_application
ru.vtb.invest
ru.vtb.smb
ru.vtb24.mobilebanking.android
ru.gazprombank.android.mobilebank.app
ru.gazprombank.broker
ru.gazprombank.mobile.gpbbusiness
com.dexp01.reoka01.com
com.dnsriteil.delivery
com.dnsriteil.dns_authenticator
com.info.smartphone.a1cmobilecomponent
ru.dns.shop.android
ru.megapolis.rms.servicedesk
ru.mos.helper
ru.mosgorpass
ru.mosmetro.metro
ru.mosparking.appnew
com.programmisty.emiasapp
ru.mgfoms.pandora
tech.clink.emias.emiasqrcode
com.discover.moscow.lite
com.moscowsport
com.tdm.messenger
org.ts.mapp
ru.altarix.mos.pgu
ru.dit.smartstaff
ru.mos.MskLongevity
ru.mos.aiso.m
ru.mos.amina.app
ru.mos.analytics.app.prod
ru.mos.app
ru.mos.cms.erzapp
ru.mos.cms.lkyo
ru.mos.dcloud.client
ru.mos.ed
ru.mos.gz
ru.mos.myid
ru.mos.ossigbuilder
ru.mos.ourcity
ru.mos.pet
ru.mos.polls
ru.mos.um
ru.netris.videocity
ru.open.gisokmp
ru.leroymerlin.employee
ru.leroymerlin.mobile
ru.oneme.app
com.equeo.megafondraiv
com.mcptt
com.megafon.kk
com.megafon.maps
com.megafon.mcca.android.store
com.megafon.rk
megafon.transport.mobile
ru.megafon.mlk
ru.megafon.vn.client
ru.megalabs.multifon
ru.netbynet.app.personal_cabinet
ru.systtech.megafon.mobile
com.pobeda.anniversary
ru.fanid
ru.gosuslugi.auto
ru.gosuslugi.culture
ru.gosuslugi.goskey
ru.gosuslugi.migrant
ru.gosuslugi.pos
ru.gosuslugi.pos.executor
ru.gosuslugi.school
ru.gosuslugi.volunteer
ru.imteleport.plp2
ru.okbmei.gosservice
ru.rostel
team.rtds.checkcontrol
com.gsgroup.secondscreen
com.gsgroup.smarthome
com.gsgroup.tricoloronline
com.gsgroup.tricoloronline.mobile
com.zebrains.trkid
ru.iflex.android.a3colortv
tv.tricolor.video
com.rzd.eventsrzd
ru.rzd.cargolk
ru.rzd.newsdo.skills
ru.rzd.pass
com.wbextdelivery
com.wbpoint.android.prod.release
com.wbstream_app
com.wildberries.consultations
com.wildberries.ru
com.wildberries.wbkey
ru.wb.courier
ru.wb.go
ru.wb.guru
ru.wb.wband
ru.wildberries.books
ru.wildberries.manager
ru.wildberries.team
ru.wildberries.team2
ru.wildberries.wbpayclient
wb.partners
wildberries.business
com.indygomobi.detifm
com.indygomobi.relaxfm
com.indygomobi.zenit
ru.ideast.humor
ru.ideast.nrj
ru.ideast.romantika
ru.ideast.ru101.rustore
ru.profmedia.avtoradio
ru.profmedia.likefm
ru.vkpm.comedy
com.drweb
com.drweb.familysecure
otello.dgis.ru
ru.dublgis.dgismobile
ru.dublgis.dgismobile4preview
com.asmo.infometeos
com.gmeteos.infometeos
com.pogoda.infometeos
ru.ivi.client
ru.ozon.app.android
ru.ozon.chatzone
ru.ozon.fintech.apvz
ru.ozon.fintech.finance
ru.ozon.fintech.sme
ru.ozon.flex
ru.ozon.fresh
ru.ozon.hire
ru.ozon.magistral
ru.ozon.maple_app
ru.ozon.ozon_pvz
ru.ozon.profit
ru.ozon.select
ru.ozon.seller_app
ru.ozon.tv
travel.ozon.mobile
com.avito.android
com.icemobile.lenta.prod
com.lenta.employee
com.lenta.lentochka_service
ru.lenta.lentochka
ru.mntk.dostavka.prod
ru.utk.dostavka
ru.litres.android
ru.litres.android.readfree
ru.litres.androidtv
ru.livelib.client
ru.mybook
com.ncloudtech.cloudoffice
com.ncloudtech.cloudoffice.b2b
ru.ncloudtech.mec
ru.ncloudtech.squadus
com.grotem.match
com.match.club
com.matchtv.rustore
business.gid.hero
business.gid.universe
ru.gazprompay.android
ru.gid.app
ru.gid.eventsapp
ru.gid.most
gpm.tnt_premier
one.premier.rustoretv
ru.ritmmedia.yappy
ru.rutube.RutubeKids
ru.rutube.app
ru.rutube.app.tv
ru.rutube.studio
ru.yota.android
chat.strelka
ru.sbcs.store
com.flowwow
ru.tntmusic.tv
ru.hh.android
ru.hh.employer.android
ru.setka
com.chaevieprosto.app
com.deliveryclub
com.edadeal.android
com.reserveonline.tablet.sr.suffix
com.routeq.app
com.yandex.aliceapp
com.yandex.bank
com.yandex.bluecollars
com.yandex.browser
com.yandex.browser.corp
com.yandex.browser.lite
com.yandex.browser.tv
com.yandex.calendar.app
com.yandex.corp.tracking.app
com.yandex.internetometer
com.yandex.iot
com.yandex.lavka
com.yandex.mobile.drive
com.yandex.mobile.realty
com.yandex.rhythm
com.yandex.searchapp
com.yandex.shedevrus
com.yandex.tasks.androidapp
com.yandex.yamb
com.zebrainy.skazbuka
home.pragma.com
home.tuvio.com
jamhome.ru.lktsj
ru.beru.android
ru.foodfox.client
ru.foodfox.vendor
ru.kinopoisk
ru.kinopoisk.tv
ru.mercaux.app
ru.plus.bookmate
ru.yandex.androidkeyboard
ru.yandex.cloud
ru.yandex.cloud.tracker
ru.yandex.direct
ru.yandex.disk
ru.yandex.drawie
ru.yandex.games
ru.yandex.games.tv
ru.yandex.key
ru.yandex.mail
ru.yandex.market.partner
ru.yandex.market.pickuppointpro
ru.yandex.metro
ru.yandex.mobile.afisha
ru.yandex.mobile.avia
ru.yandex.mobile.fmradio
ru.yandex.mobile.gasstations
ru.yandex.music
ru.yandex.practicum.flutter_practicum
ru.yandex.rasp
ru.yandex.readie
ru.yandex.rovertoy.app
ru.yandex.searchplugin
ru.yandex.smartreserve.aon
ru.yandex.subtitles
ru.yandex.taxi
ru.yandex.taximeter
ru.yandex.telemost
ru.yandex.translate
ru.yandex.travel
ru.yandex.travel.extranet
ru.yandex.uber
ru.yandex.weatherplugin
ru.yandex.yandexmaps
ru.yandex.yandexnavi
ru.yandex_team.calendar_app
ru.eapteka.courier
ru.getpharma.eapteka
ru.cian.main
com.notissimus.allinstruments.android
club.chizhik
ru.pyaterochka.app.browser
ru.x5.foodru.rs
ru.x5.key
ru.x5.mfpnew
ru.x5.mrm_android.personalDevice
ru.x5.omni
ru.x5.opermax.aura
ru.x5.rooms
ru.x5.wl.slata
ru.x5.wrs2
ru.x5.x5job
com.mvideo.mvseller
ru.filit.mvideo.b2c
ru.mvideo.service
ru.mvm.eldo
ru.newamelia.mvideo
ru.t2.wfmapp.prod
ru.tele2.app.wtt
ru.tele2.appseller
ru.tele2.cyberhero.pro
ru.tele2.mytele2
ru.tele2.nasvyzi
ru.tele2.sms.blocker
tele2.vats
ru.tutu.etrains
ru.tutu.tutu_emp
ru.ntvplus.service
tv.ntvplus.app
tv.ntvplus.app.tv
ru.sigma.gisgkh
ru.aeroflot
logo.com.mbanking
ru.psbank.invest
ru.psbank.msb.dev.psb_appstore
sodruzhestvo.android.app
com.iwedia.ui.beeline.atv
com.spbtv.rosing
intech.global.com.beeline
ru.beeline.beebookreader
ru.beeline.cloud
ru.beeline.dol
ru.beeline.messengerx
ru.beeline.mwpsapp
ru.beeline.pro
ru.beeline.services
ru.beeline.tve.android
com.kazanexpress.ke_app
com.magnit.delivery.courier
com.wms_mm_point.mm_delivery_point
ru.compass.tag
ru.magnit.hrtest.android
ru.magnit.mesmag
ru.magnit.tag
ru.magnit.tms.armhde
ru.magnit.vendorapp
ru.tander.magnit
ru.tander.mobile_scout_flutter
com.birzha_rt
com.dartit.RTcabinet
com.dartit.mobileagent
com.rostelecom.printservice
org.rtk.cleaning
ru.onlime.my.app
ru.rostelecom.ideas
ru.rostelecom.vatsmobilelk
ru.rt.key
ru.rt.life
ru.rt.masterkey
ru.rt.mb_installer
ru.rt.mobileoffice
ru.rt.ritm
ru.rt.smarthome
ru.rt.video.app.mobile.b2b
ru.rt.videocomfort
ru.rt.wfm
ru.rtdc.kakdela
ru.yozhka
com.goodok.mts
com.mts.who_calls
me.membrana.kids.parent.app
ru.mts.books.droid
ru.mts.live.app
ru.mts.mtscode
ru.mts.mtstv
ru.mts.music.android
ru.mts.mymts
ru.mts.pay
ru.mts.twomem
ru.mts.vdome.resident
com.navplatform.navigator.public
com.sberbank.sberpravo
com.sdkit.search.app
ru.sber.csradar
ru.sberbank.investor
ru.sberbank.onlineencashment
ru.sberbank.sberkids
ru.sberbank.sbersign
ru.sberbank_sbbol
ru.sberbankmobile
psb.market.app
ru.perekrestok.app
ru.pikabu.android
com.octopod.russianpost.client.android
ru.russianpost.pechkin
com.mcd.superapp
ru.ideast.championat
ru.rambler.horoscopes.twa
ru.rambler.mail
ru.rt.video.app.mobile
ru.rt.video.app.tv
ru.wink.music
ru.wink.music.tv
ru.fdoctor.fdocmob
ru.crpt.localmodule
ru.crptech.b2bmark
ru.crptech.foiv
ru.crptech.mark
ru.crptech.pharma_scanner
com.b2bdomru.domrubusiness
com.ertelecom.agent
com.ertelecom.domrutv
com.ertelecom.domrutvstb
com.ertelecom.smarthome
com.ertelecom.vats
ru.cctvb2b.dom.app

Короче, проще считать скурвившимися все приложения.

было бы неплохо в табличку выгрузить
Название приложения | ID пакета | Ссылка на стор

list.md (52.5 KB)

У кого самсунг, кто-то ставил Mir Pay в Knox? Он у вас работал?

есть список для sing-box