web-dev-qa-db-fra.com

Vidage de la mémoire Android

J'ai besoin d'évaluer la sécurité d'une bibliothèque cryptographique. En particulier, je cible une partie de la bibliothèque où je pense que la clé privée est exposée pendant un temps limité dans la RAM. Des idées ou des conseils sur la façon de vérifier la RAM pour cette clé. Je pensais à vider la mémoire après certaines interactions utilisateur spécifiques. Mais comment commencer avec cela, des outils recommandés? I suis à la maison dans le monde de la sécurité, je connais les dispositions de la mémoire, l'utilisation, les contre-mesures contre les attaques de mémoire, etc. Tout simplement pas dans Android.

Quant à Starter, il suffit que les outils/techniques nécessitent un flash personnalisé du noyau ou des périphériques rootés. Mais en fin de compte, il devrait être applicable dans des situations réelles où le périphérique cible est un périphérique OEM prêt à l'emploi.

19
4oxer

J'avais le même besoin et après avoir regardé autour de moi, j'ai fini par écrire mon propre programme.

Usage:

memdump <pid>
memdump <pid> <ip-address> <port>

Le premier affichera toute la mémoire du processus sur stdout, et le second sur le port TCP de votre choix (vous utiliserez probablement netcat à l'autre extrémité).

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/ptrace.h>
#include <sys/socket.h>
#include <arpa/inet.h>

void dump_memory_region(FILE* pMemFile, unsigned long start_address, long length, int serverSocket)
{
    unsigned long address;
    int pageLength = 4096;
    unsigned char page[pageLength];
    fseeko(pMemFile, start_address, SEEK_SET);

    for (address=start_address; address < start_address + length; address += pageLength)
    {
        fread(&page, 1, pageLength, pMemFile);
        if (serverSocket == -1)
        {
            // write to stdout
            fwrite(&page, 1, pageLength, stdout);
        }
        else
        {
            send(serverSocket, &page, pageLength, 0);
        }
    }
}

int main(int argc, char **argv) {

    if (argc == 2 || argc == 4)
    {
        int pid = atoi(argv[1]);
        long ptraceResult = ptrace(PTRACE_ATTACH, pid, NULL, NULL);
        if (ptraceResult < 0)
        {
            printf("Unable to attach to the pid specified\n");
            return;
        }
        wait(NULL);

        char mapsFilename[1024];
        sprintf(mapsFilename, "/proc/%s/maps", argv[1]);
        FILE* pMapsFile = fopen(mapsFilename, "r");
        char memFilename[1024];
        sprintf(memFilename, "/proc/%s/mem", argv[1]);
        FILE* pMemFile = fopen(memFilename, "r");
        int serverSocket = -1;
        if (argc == 4)
        {   
            unsigned int port;
            int count = sscanf(argv[3], "%d", &port);
            if (count == 0)
            {
                printf("Invalid port specified\n");
                return;
            }
            serverSocket = socket(AF_INET, SOCK_STREAM, 0);
            if (serverSocket == -1)
            {
                printf("Could not create socket\n");
                return;
            }
            struct sockaddr_in serverSocketAddress;
            serverSocketAddress.sin_addr.s_addr = inet_addr(argv[2]);
            serverSocketAddress.sin_family = AF_INET;
            serverSocketAddress.sin_port = htons(port);
            if (connect(serverSocket, (struct sockaddr *) &serverSocketAddress, sizeof(serverSocketAddress)) < 0)
            {
                printf("Could not connect to server\n");
                return;
            }
        }
        char line[256];
        while (fgets(line, 256, pMapsFile) != NULL)
        {
            unsigned long start_address;
            unsigned long end_address;
            sscanf(line, "%08lx-%08lx\n", &start_address, &end_address);
            dump_memory_region(pMemFile, start_address, end_address - start_address, serverSocket);
        }
        fclose(pMapsFile);
        fclose(pMemFile);
        if (serverSocket != -1)
        {
            close(serverSocket);
        }

        ptrace(PTRACE_CONT, pid, NULL, NULL);
        ptrace(PTRACE_DETACH, pid, NULL, NULL);
    }
    else
    {
        printf("%s <pid>\n", argv[0]);
        printf("%s <pid> <ip-address> <port>\n", argv[0]);
        exit(0);
    }
}

Pour le compiler de manière croisée pour Android votre Android.mk devrait ressembler à ceci:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := memdump
LOCAL_SRC_FILES := memdump.c
include $(BUILD_EXECUTABLE)
11
Tal Aloni

Vous pouvez vider les informations de la mémoire à l'aide de Android Debug Bridge (ADB) à l'aide de la commande suivante:

adb Shell dumpsys meminfo > mem.txt

Pour obtenir des informations sur une application particulière, utilisez ceci:

adb Shell dumpsys meminfo 'your apps package name'

Cette réponse donne un aperçu détaillé de l'outil dumpsys . Jetez un oeil. En outre, ce billet de blog explique une autre méthode pour vider la mémoire d'un processus en cours d'exécution (je viens de le trouver dans mon résultat de recherche Google).

9
Rahil Arora

Vous avez également un outil intégré dans Android-Studio pour cela, qui est appelé "Profiler".

Vous pouvez profiler à partir de:

  1. Attachez le profileur à l'appareil ( plus d'explications ici )
  2. fichier hprof (peut être généré par la commande 'heapdump' dans le shell de l'appareil)

Exemple d'utilisation du profileur:

Profiler Example

1
user3467955

Il existe des techniques pour capturer le Android RAM dans un fichier mémoire ou un vidage comme vous le feriez avec n'importe quel OS de bureau et analyser le vidage mem en utilisant un cadre comme la volatilité .Pour Android il est plus que probable que vous ayez à rooter l'appareil. Si vous avez le temps, il s'agit d'un excellent guide en deux parties sur l'extraction de la mémoire Android qui commence ici https://www.youtube.com/watch?v=KN9kxn6htM

En utilisant la volatilité, vous pouvez extraire des chaînes, voir le processus en cours d'exécution, etc. La fondation de la volatilité a un excellent article de blog ici sur l'identification des clés de chiffrement AES pour une véritable crypte dans un vidage de mémoire. http://volatility-labs.blogspot.com/2014/01/truecrypt-master-key-extraction-and.html

Il semble que vous puissiez utiliser une méthodologie très similaire dans votre cas d'utilisation. J'espère que cela pourra vous être utile.

0
Escher

Vous pouvez utiliser GameGuardian pour cela. Besoin de racine.

Onglet Editeur de mémoire - menu - vidage de la mémoire - sélectionnez la plage et le dossier - appuyez sur ok - attendez le toast "Dump end".

Voici quelques exemples de vidéos sur la façon de procéder:

0
Enyby