Ukrywanie ciągów w zakodowanym kodzie

Po prostu Zaciemniłem kod Androida za pomocą proguarda, a następnie go dekompilowałem. Jest wiele strun, które chciałbym ukryć przed wzrokiem ciekawskich. Kiedy dekompilowałem mój kod, struny były tam dla wszystkich...i zmiany. Jednym z łańcuchów jest adres URL do mojego serwera licencyjnego i mogą w efekcie zmienić adres url, aby wskazać fałszywy serwer(ponieważ będę udostępniać kod serwera publicznie). Jaki jest najlepszy sposób na ukrycie tego typu informacje?

Zauważyłem również, że łańcuchy klasy R są przypadkowymi liczbami, ale nie mogę znaleźć klasy R w dekompilowanym kodzie. Gdzie to jest?

Przykład Foe widzę: new SimpleCursorAdapter(localActivity, 2130903058, localCursor, arrayOfString, arrayOfInt);

2130903058 to plik układu graficznego, ale do czego się odnosi? Numer nic nie znaczy, chyba że wskazuje na jakiś adres.

Author: Antonio, 2010-12-13

7 answers

Zakładając, że jesteś zadowolony z niejasnych, a nie bezpiecznych, istnieje wiele mechanizmów, których możesz użyć, ale zaciemniacze, tacy jak proguard, nie będą w stanie Ci pomóc.

Aby to osiągnąć, będziesz musiał samodzielnie kodować lub szyfrować ciąg znaków, podejście, którego używasz, zależy od tego, przed czym próbujesz się bronić, jeśli po prostu próbujesz ukryć się przed oczywistą inspekcją, kodowanie może być wystarczające (zobacz android.util.Base64, http://developer.android.com/reference/android/util/Base64.html ). zauważ, że kodowanie nie jest w żaden sposób bezpieczne i wystarczy usunąć oczywiste odniesienie do twojej witryny.

Jeśli próbujesz bronić się przed czymś więcej, możesz przejść do szyfrowania łańcucha znaków, aby to zrobić, użyj symetrycznego szyfru, takiego jak AES via javax.krypto.Szyfr, http://www.androidsnippets.org/snippets/39/index.html zapewnia przyzwoity przykład użycia. Znowu to jest bardziej irytujące, a następnie bezpieczne będą hakerzy, ponieważ będziesz musiał przechowywać klucz gdzieś w swoim słoiku, negując w ten sposób wszelkie zabezpieczenia kryptograficzne.

Aby było to jaśniejsze, podstawowe kroki byłyby następujące:

  1. ręcznie utwórz Zaszyfruj swój łańcuch za pomocą znanego klucza.
  2. Konwertuj kod na odszyfrowaną wersję tego ciągu, przykład:

Przed:

public class Foo {
    private String mySecret = "http://example.com";

    ...
}

Staje się:

public class Foo {
    private String encrypted = "<manually created encrypted string>";
    private String key = "<key used for encryption";
    private String mySecret = MyDecryptUtil.decrypt(encrypted, key);

    ...
}

(dobrą) alternatywą dla tego wszystkiego jest rozważenie użycia trzeciego firmowe rozwiązanie drm, takie jak serwer licencyjny google zapewnia http://android-developers.blogspot.com/2010/07/licensing-service-for-android.html . może to być bezpieczniejsze niż coś, co się toczy, ale podlega bardzo podobnym ograniczeniom do tego, co opisałem powyżej.

 33
Author: Mark Hibberd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-13 09:40:51

Cześć wszystkim.

  1. Niech secret będzie tekstem, który chcesz ukryć

  2. Znajdź keyhash twojego debug / release.keystore. Niech {[2] } będzie tym kluczem.

(użyj narzędzi keytool+openssl: keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64 )

  1. Użyj narzędzia (zewnętrznego do kodu Androida) do szyfrowania secret za pomocą k1

    encrypted = encode (secret, k1)

(na przykład: https://jwt.io , dla Javy: https://github.com/jwtk/jjwt).

  1. w Twoim kodzie Java na Androida Zapisz encrypted. Gdy potrzebujesz zdekodowanej wersji encrypted (jest to oryginalna secret) napisz

original = decode(encrypted, get_my_keyhash_programmatically() )

To wszystko. to działa, ponieważ oryginalny {[1] } nie jest wyświetlany w kodzie źródłowym Javy, ani {[2] } do jego dekodowania. A jeśli haker chce wydrukować twoje odkodowany sekret, musi zmienić kod i przekompilować, podpisując swój .apk z własnym kluczem, a nie z Twoim, a tym samym brak odpowiedniego oryginału secret. ("Jedynym" punktem jest to, czy k1 można dowiedzieć się z oryginału .apk).

Uwaga: get_my_keyhash_programmatic ():

try {
    PackageInfo info = getPackageManager().getPackageInfo(
            "el nombre de su paquete por ejemplo com.tarea.u8",
            PackageManager.GET_SIGNATURES);
    for (Signature signature : info.signatures) {
        MessageDigest md = MessageDigest.getInstance("SHA");
        md.update(signature.toByteArray());
        Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT));
    }
} catch (PackageManager.NameNotFoundException e) {

} catch (NoSuchAlgorithmException e) {

}
 24
Author: cibercitizen1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

To, co zrobiłem, to stworzenie długiej listy ciągów statycznych w mojej klasie użyteczności globalnej. Gdzieś w obrębie długiej listy ciągów umieściłem mój kod w wielu kawałkach.

Z moim kodem łatwo jest zobaczyć, jakie są prawdziwe kody-ale gdy obfuscator zacznie działać, wszystkie statyki będą miały nazwę A, B, C itp. i nie będzie już łatwo to zauważyć.

 8
Author: Someone Somewhere,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-08 03:35:53

Użyłem ROT47. Nie jest zbyt bezpieczny, ale łatwy w użyciu i implementacji, ponieważ jest to koder/dekoder symetryczny

 2
Author: w_g,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-02 06:54:04

Powinieneś wygooglować dla "Just another Perl hacker". Są to programy, które wypisują ciąg znaków z zaciemnionym kodem. Istnieje również wiele przykładów w innych językach niż Perl w sieci.

Wpis do Wikipedii

 1
Author: iuiz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-13 10:18:43

Możesz użyć DexGuard do szyfrowania łańcuchów, prawdopodobnie skuteczniej niż można to osiągnąć ręcznie, bez obciążania kodu źródłowego.

 0
Author: Ahmad Ronagh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-20 00:28:45

Oto co obecnie używam ma hacki do obsługi funkcji sprintf, które rozlały zwykły tekst w skompilowanym pliku binarnym. Możesz teraz użyć w_sprintf_s zamiast sprintf, tak jak

char test[256] = { 0 };
w_sprintf_s(test, 256, XorStr("test test :D %d %+d\n"), 1, 1337);

Lub użyj go w ten sposób, aby wydrukować rzeczy na ekranie, na przykład

w_printf(XorStr("test I print this and can't see me inside .dll or .exe"));

Działa na zmiennych, jeśli masz niestandardową printf (), możesz jej również użyć..

char szGuid[255] = { 0 };
//generate serial code removed.
char finalSerial[512] = { 0 };
XorCompileTime::w_sprintf(finalSerial, XorStr("serial information=%s"), szGuid);
myprintf(XorStr("Your Hardware ID: %s\n"), szGuid);


Może dodać wsparcie dla szerokich łańcuchów wgar_t, tak jak arkan.. ale nie mam z nich teraz pożytku, bo nie piszę wszystko w symbols / unicode.

Oto plik po prostu zmień nazwę poniższego kodu na XorString.h i dołącz go do swojego projektu w prosty sposób

#pragma once
#include <string>
#include <array>
#include <cstdarg>

#define BEGIN_NAMESPACE( x ) namespace x {
#define END_NAMESPACE }

BEGIN_NAMESPACE(XorCompileTime)

constexpr auto time = __TIME__;
constexpr auto seed = static_cast< int >(time[7]) + static_cast< int >(time[6]) * 10 + static_cast< int >(time[4]) * 60 + static_cast< int >(time[3]) * 600 + static_cast< int >(time[1]) * 3600 + static_cast< int >(time[0]) * 36000;

// 1988, Stephen Park and Keith Miller
// "Random Number Generators: Good Ones Are Hard To Find", considered as "minimal standard"
// Park-Miller 31 bit pseudo-random number generator, implemented with G. Carta's optimisation:
// with 32-bit math and without division

template < int N >
struct RandomGenerator
{
private:
    static constexpr unsigned a = 16807; // 7^5
    static constexpr unsigned m = 2147483647; // 2^31 - 1

    static constexpr unsigned s = RandomGenerator< N - 1 >::value;
    static constexpr unsigned lo = a * (s & 0xFFFF); // Multiply lower 16 bits by 16807
    static constexpr unsigned hi = a * (s >> 16); // Multiply higher 16 bits by 16807
    static constexpr unsigned lo2 = lo + ((hi & 0x7FFF) << 16); // Combine lower 15 bits of hi with lo's upper bits
    static constexpr unsigned hi2 = hi >> 15; // Discard lower 15 bits of hi
    static constexpr unsigned lo3 = lo2 + hi;

public:
    static constexpr unsigned max = m;
    static constexpr unsigned value = lo3 > m ? lo3 - m : lo3;
};

template <>
struct RandomGenerator< 0 >
{
    static constexpr unsigned value = seed;
};

template < int N, int M >
struct RandomInt
{
    static constexpr auto value = RandomGenerator< N + 1 >::value % M;
};

template < int N >
struct RandomChar
{
    static const char value = static_cast< char >(1 + RandomInt< N, 0x7F - 1 >::value);
};

template < size_t N, int K >
struct XorString
{
private:
    const char _key;
    std::array< char, N + 1 > _encrypted;

    constexpr char enc(char c) const
    {
        return c ^ _key;
    }

    char dec(char c) const
    {
        return c ^ _key;
    }

public:
    template < size_t... Is >
    constexpr __forceinline XorString(const char* str, std::index_sequence< Is... >) : _key(RandomChar< K >::value), _encrypted{ enc(str[Is])... }
    {
    }

    __forceinline decltype(auto) decrypt(void)
    {
        for (size_t i = 0; i < N; ++i) {
            _encrypted[i] = dec(_encrypted[i]);
        }
        _encrypted[N] = '\0';
        return _encrypted.data();
    }
};

//--------------------------------------------------------------------------------
//-- Note: XorStr will __NOT__ work directly with functions like printf.
//         To work with them you need a wrapper function that takes a const char*
//         as parameter and passes it to printf and alike.
//
//         The Microsoft Compiler/Linker is not working correctly with variadic 
//         templates!
//  
//         Use the functions below or use std::cout (and similar)!
//--------------------------------------------------------------------------------

static auto w_printf = [](const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vprintf_s(fmt, args);
    va_end(args);
};

static auto w_printf_s = [](const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vprintf_s(fmt, args);
    va_end(args);
};

static auto w_sprintf = [](char* buf, const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vsprintf(buf, fmt, args);
    va_end(args);
};

static auto w_sprintf_s = [](char* buf, size_t buf_size, const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vsprintf_s(buf, buf_size, fmt, args);
    va_end(args);
};

#define XorStr( s ) ( XorCompileTime::XorString< sizeof( s ) - 1, __COUNTER__ >( s, std::make_index_sequence< sizeof( s ) - 1>() ).decrypt() )

END_NAMESPACE
 0
Author: SSpoke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-10 10:15:11