mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-11 01:31:37 +00:00
Merge pull request #695 from joeyjiaojg/dev
Fix Porting of AFLplusplus for Android
This commit is contained in:
commit
b9e855b7b5
180
Android.bp
180
Android.bp
@ -1,7 +1,16 @@
|
||||
cc_defaults {
|
||||
name: "afl-defaults",
|
||||
sanitize: {
|
||||
never: true,
|
||||
},
|
||||
|
||||
local_include_dirs: [
|
||||
"include",
|
||||
"instrumentation",
|
||||
],
|
||||
|
||||
cflags: [
|
||||
"-flto=full",
|
||||
"-funroll-loops",
|
||||
"-Wno-pointer-sign",
|
||||
"-Wno-pointer-arith",
|
||||
@ -10,16 +19,22 @@ cc_defaults {
|
||||
"-Wno-unused-function",
|
||||
"-Wno-format",
|
||||
"-Wno-user-defined-warnings",
|
||||
"-DUSE_TRACE_PC=1",
|
||||
"-DAFL_LLVM_USE_TRACE_PC=1",
|
||||
"-DBIN_PATH=\"out/host/linux-x86/bin\"",
|
||||
"-DDOC_PATH=\"out/host/linux-x86/shared/doc/afl\"",
|
||||
"-D__USE_GNU",
|
||||
"-D__aarch64__",
|
||||
"-DDEBUG_BUILD",
|
||||
"-U_FORTIFY_SOURCE",
|
||||
"-ggdb3",
|
||||
"-g",
|
||||
"-O0",
|
||||
"-fno-omit-frame-pointer",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "afl-fuzz",
|
||||
static_executable: true,
|
||||
host_supported: true,
|
||||
|
||||
defaults: [
|
||||
@ -27,7 +42,11 @@ cc_binary {
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"afl-fuzz.c",
|
||||
"src/afl-fuzz*.c",
|
||||
"src/afl-common.c",
|
||||
"src/afl-sharedmem.c",
|
||||
"src/afl-forkserver.c",
|
||||
"src/afl-performance.c",
|
||||
],
|
||||
}
|
||||
|
||||
@ -41,7 +60,10 @@ cc_binary {
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"afl-showmap.c",
|
||||
"src/afl-showmap.c",
|
||||
"src/afl-common.c",
|
||||
"src/afl-sharedmem.c",
|
||||
"src/afl-forkserver.c",
|
||||
],
|
||||
}
|
||||
|
||||
@ -55,7 +77,11 @@ cc_binary {
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"afl-tmin.c",
|
||||
"src/afl-tmin.c",
|
||||
"src/afl-common.c",
|
||||
"src/afl-sharedmem.c",
|
||||
"src/afl-forkserver.c",
|
||||
"src/afl-performance.c",
|
||||
],
|
||||
}
|
||||
|
||||
@ -69,7 +95,10 @@ cc_binary {
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"afl-analyze.c",
|
||||
"src/afl-analyze.c",
|
||||
"src/afl-common.c",
|
||||
"src/afl-sharedmem.c",
|
||||
"src/afl-performance.c",
|
||||
],
|
||||
}
|
||||
|
||||
@ -83,12 +112,13 @@ cc_binary {
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"afl-gotcpu.c",
|
||||
"src/afl-gotcpu.c",
|
||||
"src/afl-common.c",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary_host {
|
||||
name: "afl-clang-fast",
|
||||
name: "afl-cc",
|
||||
static_executable: true,
|
||||
|
||||
defaults: [
|
||||
@ -98,28 +128,25 @@ cc_binary_host {
|
||||
cflags: [
|
||||
"-D__ANDROID__",
|
||||
"-DAFL_PATH=\"out/host/linux-x86/lib64\"",
|
||||
"-DAFL_CLANG_FLTO=\"-flto=full\"",
|
||||
"-DUSE_BINDIR=1",
|
||||
"-DLLVM_BINDIR=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin\"",
|
||||
"-DLLVM_LIBDIR=\"prebuilts/clang/host/linux-x86/clang-r383902b/lib64\"",
|
||||
"-DCLANGPP_BIN=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin/clang++\"",
|
||||
"-DAFL_REAL_LD=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin/ld.lld\"",
|
||||
"-DLLVM_LTO=1",
|
||||
"-DLLVM_MAJOR=11",
|
||||
"-DLLVM_MINOR=2",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"src/afl-cc.c",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary_host {
|
||||
name: "afl-clang-fast++",
|
||||
static_executable: true,
|
||||
|
||||
defaults: [
|
||||
"afl-defaults",
|
||||
"src/afl-common.c",
|
||||
],
|
||||
|
||||
cflags: [
|
||||
"-D__ANDROID__",
|
||||
"-DAFL_PATH=\"out/host/linux-x86/lib64\"",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"src/afl-cc.c",
|
||||
symlinks: [
|
||||
"afl-clang-fast",
|
||||
"afl-clang-fast++",
|
||||
],
|
||||
}
|
||||
|
||||
@ -131,11 +158,114 @@ cc_library_static {
|
||||
recovery_available: true,
|
||||
sdk_version: "9",
|
||||
|
||||
apex_available: [
|
||||
"com.android.adbd",
|
||||
"com.android.appsearch",
|
||||
"com.android.art",
|
||||
"com.android.bluetooth.updatable",
|
||||
"com.android.cellbroadcast",
|
||||
"com.android.conscrypt",
|
||||
"com.android.extservices",
|
||||
"com.android.cronet",
|
||||
"com.android.neuralnetworks",
|
||||
"com.android.media",
|
||||
"com.android.media.swcodec",
|
||||
"com.android.mediaprovider",
|
||||
"com.android.permission",
|
||||
"com.android.runtime",
|
||||
"com.android.resolv",
|
||||
"com.android.tethering",
|
||||
"com.android.wifi",
|
||||
"com.android.sdkext",
|
||||
"com.android.os.statsd",
|
||||
"//any",
|
||||
],
|
||||
|
||||
defaults: [
|
||||
"afl-defaults",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"instrumentation/afl-llvm-rt.o.c",
|
||||
"instrumentation/afl-compiler-rt.o.c",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_headers {
|
||||
name: "libafl_headers",
|
||||
vendor_available: true,
|
||||
host_supported: true,
|
||||
|
||||
export_include_dirs: [
|
||||
"include",
|
||||
],
|
||||
}
|
||||
|
||||
cc_prebuilt_library_static {
|
||||
name: "libfrida-gum",
|
||||
compile_multilib: "64",
|
||||
strip: {
|
||||
none: true,
|
||||
},
|
||||
|
||||
srcs: [
|
||||
"utils/afl_frida/android/libfrida-gum.a",
|
||||
],
|
||||
|
||||
export_include_dirs: [
|
||||
"utils/afl_frida/android",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libtestinstr",
|
||||
|
||||
srcs: [
|
||||
"utils/afl_frida/libtestinstr.c",
|
||||
],
|
||||
|
||||
cflags: [
|
||||
"-O0",
|
||||
"-fPIC",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "afl-frida",
|
||||
compile_multilib: "64",
|
||||
|
||||
defaults: [
|
||||
"afl-defaults",
|
||||
],
|
||||
|
||||
cflags: [
|
||||
"-g",
|
||||
"-O0",
|
||||
"-Wno-format",
|
||||
"-Wno-pointer-sign",
|
||||
"-fpermissive",
|
||||
"-fPIC",
|
||||
],
|
||||
|
||||
static_libs: [
|
||||
"afl-llvm-rt",
|
||||
"libfrida-gum",
|
||||
],
|
||||
|
||||
shared_libs: [
|
||||
"libdl",
|
||||
"liblog",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"utils/afl_frida/afl-frida.c",
|
||||
],
|
||||
|
||||
local_include_dirs: [
|
||||
"utils/afl_frida",
|
||||
"utils/afl_frida/android",
|
||||
],
|
||||
}
|
||||
|
||||
subdirs = [
|
||||
"custom_mutators",
|
||||
]
|
||||
|
@ -1 +0,0 @@
|
||||
Makefile
|
@ -1107,7 +1107,7 @@ without feedback, bug reports, or patches from:
|
||||
Khaled Yakdan Kuang-che Wu
|
||||
Josephine Calliotte Konrad Welc
|
||||
Thomas Rooijakkers David Carlier
|
||||
Ruben ten Hove
|
||||
Ruben ten Hove Joey Jiao
|
||||
```
|
||||
|
||||
Thank you!
|
||||
|
115
custom_mutators/Android.bp
Normal file
115
custom_mutators/Android.bp
Normal file
@ -0,0 +1,115 @@
|
||||
cc_library_shared {
|
||||
name: "libfuzzer-mutator",
|
||||
vendor_available: true,
|
||||
host_supported: true,
|
||||
|
||||
cflags: [
|
||||
"-g",
|
||||
"-O0",
|
||||
"-funroll-loops",
|
||||
"-fPIC",
|
||||
"-fpermissive",
|
||||
"-std=c++11",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"libfuzzer/FuzzerCrossOver.cpp",
|
||||
"libfuzzer/FuzzerDataFlowTrace.cpp",
|
||||
"libfuzzer/FuzzerDriver.cpp",
|
||||
"libfuzzer/FuzzerExtFunctionsDlsym.cpp",
|
||||
"libfuzzer/FuzzerExtFunctionsWeak.cpp",
|
||||
"libfuzzer/FuzzerExtFunctionsWindows.cpp",
|
||||
"libfuzzer/FuzzerExtraCounters.cpp",
|
||||
"libfuzzer/FuzzerFork.cpp",
|
||||
"libfuzzer/FuzzerIO.cpp",
|
||||
"libfuzzer/FuzzerIOPosix.cpp",
|
||||
"libfuzzer/FuzzerIOWindows.cpp",
|
||||
"libfuzzer/FuzzerLoop.cpp",
|
||||
"libfuzzer/FuzzerMerge.cpp",
|
||||
"libfuzzer/FuzzerMutate.cpp",
|
||||
"libfuzzer/FuzzerSHA1.cpp",
|
||||
"libfuzzer/FuzzerTracePC.cpp",
|
||||
"libfuzzer/FuzzerUtil.cpp",
|
||||
"libfuzzer/FuzzerUtilDarwin.cpp",
|
||||
"libfuzzer/FuzzerUtilFuchsia.cpp",
|
||||
"libfuzzer/FuzzerUtilLinux.cpp",
|
||||
"libfuzzer/FuzzerUtilPosix.cpp",
|
||||
"libfuzzer/FuzzerUtilWindows.cpp",
|
||||
"libfuzzer/libfuzzer.cpp",
|
||||
],
|
||||
|
||||
header_libs: [
|
||||
"libafl_headers",
|
||||
],
|
||||
}
|
||||
|
||||
/*cc_library_shared {
|
||||
name: "honggfuzz-mutator",
|
||||
vendor_available: true,
|
||||
host_supported: true,
|
||||
|
||||
cflags: [
|
||||
"-g",
|
||||
"-O0",
|
||||
"-funroll-loops",
|
||||
"-fPIC",
|
||||
"-Wl,-Bsymbolic",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"honggfuzz/honggfuzz.c",
|
||||
"honggfuzz/mangle.c",
|
||||
// "../src/afl-perfomance.c",
|
||||
],
|
||||
|
||||
header_libs: [
|
||||
"libafl_headers",
|
||||
],
|
||||
}*/
|
||||
|
||||
cc_library_shared {
|
||||
name: "radamsa-mutator",
|
||||
vendor_available: true,
|
||||
host_supported: true,
|
||||
|
||||
cflags: [
|
||||
"-g",
|
||||
"-O0",
|
||||
"-funroll-loops",
|
||||
"-fPIC",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"radamsa/libradamsa.c",
|
||||
"radamsa/radamsa-mutator.c",
|
||||
],
|
||||
|
||||
header_libs: [
|
||||
"libafl_headers",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "symcc-mutator",
|
||||
vendor_available: true,
|
||||
host_supported: true,
|
||||
|
||||
cflags: [
|
||||
"-g",
|
||||
"-O0",
|
||||
"-funroll-loops",
|
||||
"-fPIC",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"symcc/symcc.c",
|
||||
],
|
||||
|
||||
header_libs: [
|
||||
"libafl_headers",
|
||||
],
|
||||
}
|
||||
|
||||
subdirs = [
|
||||
"libprotobuf-mutator-example",
|
||||
]
|
32
custom_mutators/libprotobuf-mutator-example/Android.bp
Normal file
32
custom_mutators/libprotobuf-mutator-example/Android.bp
Normal file
@ -0,0 +1,32 @@
|
||||
cc_library_shared {
|
||||
name: "libprotobuf-mutator-example-afl",
|
||||
vendor_available: true,
|
||||
host_supported: true,
|
||||
|
||||
cflags: [
|
||||
"-g",
|
||||
"-O0",
|
||||
"-fPIC",
|
||||
"-Wall",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"lpm_aflpp_custom_mutator_input.cc",
|
||||
"test.proto",
|
||||
],
|
||||
|
||||
shared_libs: [
|
||||
"libprotobuf-cpp-full",
|
||||
"libprotobuf-mutator",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "libprotobuf-mutator-vuln",
|
||||
vendor_available: true,
|
||||
host_supported: true,
|
||||
|
||||
srcs: [
|
||||
"vuln.c",
|
||||
],
|
||||
}
|
1
custom_mutators/libprotobuf-mutator-example/README.md
Normal file
1
custom_mutators/libprotobuf-mutator-example/README.md
Normal file
@ -0,0 +1 @@
|
||||
Ported from [https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/5_libprotobuf_aflpp_custom_mutator_input](https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/5_libprotobuf_aflpp_custom_mutator_input)
|
@ -0,0 +1,118 @@
|
||||
#include "lpm_aflpp_custom_mutator_input.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
using std::cin;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
std::string ProtoToData(const TEST &test_proto) {
|
||||
std::stringstream all;
|
||||
const auto &aa = test_proto.a();
|
||||
const auto &bb = test_proto.b();
|
||||
all.write((const char*)&aa, sizeof(aa));
|
||||
if(bb.size() != 0) {
|
||||
all.write(bb.c_str(), bb.size());
|
||||
}
|
||||
|
||||
std::string res = all.str();
|
||||
if (bb.size() != 0 && res.size() != 0) {
|
||||
// set PROTO_FUZZER_DUMP_PATH env to dump the serialized protobuf
|
||||
if (const char *dump_path = getenv("PROTO_FUZZER_DUMP_PATH")) {
|
||||
std::ofstream of(dump_path);
|
||||
of.write(res.data(), res.size());
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize this custom mutator
|
||||
*
|
||||
* @param[in] afl a pointer to the internal state object. Can be ignored for
|
||||
* now.
|
||||
* @param[in] seed A seed for this mutator - the same seed should always mutate
|
||||
* in the same way.
|
||||
* @return Pointer to the data object this custom mutator instance should use.
|
||||
* There may be multiple instances of this mutator in one afl-fuzz run!
|
||||
* Return NULL on error.
|
||||
*/
|
||||
extern "C" MyMutator *afl_custom_init(void *afl, unsigned int seed) {
|
||||
MyMutator *mutator = new MyMutator();
|
||||
|
||||
mutator->RegisterPostProcessor(
|
||||
TEST::descriptor(),
|
||||
[](google::protobuf::Message* message, unsigned int seed) {
|
||||
// libprotobuf-mutator's built-in mutator is kind of....crappy :P
|
||||
// Even a dumb fuzz like `TEST.a = rand();` is better in this case... Q_Q
|
||||
// We register a post processor to apply our dumb fuzz
|
||||
|
||||
TEST *t = static_cast<TEST *>(message);
|
||||
t->set_a(rand());
|
||||
});
|
||||
|
||||
srand(seed);
|
||||
return mutator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform custom mutations on a given input
|
||||
*
|
||||
* @param[in] data pointer returned in afl_custom_init for this fuzz case
|
||||
* @param[in] buf Pointer to input data to be mutated
|
||||
* @param[in] buf_size Size of input data
|
||||
* @param[out] out_buf the buffer we will work on. we can reuse *buf. NULL on
|
||||
* error.
|
||||
* @param[in] add_buf Buffer containing the additional test case
|
||||
* @param[in] add_buf_size Size of the additional test case
|
||||
* @param[in] max_size Maximum size of the mutated output. The mutation must not
|
||||
* produce data larger than max_size.
|
||||
* @return Size of the mutated output.
|
||||
*/
|
||||
extern "C" size_t afl_custom_fuzz(MyMutator *mutator, // return value from afl_custom_init
|
||||
uint8_t *buf, size_t buf_size, // input data to be mutated
|
||||
uint8_t **out_buf, // output buffer
|
||||
uint8_t *add_buf, size_t add_buf_size, // add_buf can be NULL
|
||||
size_t max_size) {
|
||||
// This function can be named either "afl_custom_fuzz" or "afl_custom_mutator"
|
||||
// A simple test shows that "buf" will be the content of the current test case
|
||||
// "add_buf" will be the next test case ( from AFL++'s input queue )
|
||||
|
||||
TEST input;
|
||||
// parse input data to TEST
|
||||
// Notice that input data should be a serialized protobuf data
|
||||
// Check ./in/ii and test_protobuf_serializer for more detail
|
||||
bool parse_ok = input.ParseFromArray(buf, buf_size);
|
||||
if(!parse_ok) {
|
||||
// Invalid serialize protobuf data. Don't mutate.
|
||||
// Return a dummy buffer. Also mutated_size = 0
|
||||
static uint8_t *dummy = new uint8_t[10]; // dummy buffer with no data
|
||||
*out_buf = dummy;
|
||||
return 0;
|
||||
}
|
||||
// mutate the protobuf
|
||||
mutator->Mutate(&input, max_size);
|
||||
|
||||
// Convert protobuf to raw data
|
||||
const TEST *p = &input;
|
||||
std::string s = ProtoToData(*p);
|
||||
// Copy to a new buffer ( mutated_out )
|
||||
size_t mutated_size = s.size() <= max_size ? s.size() : max_size; // check if raw data's size is larger than max_size
|
||||
uint8_t *mutated_out = new uint8_t[mutated_size+1];
|
||||
memcpy(mutated_out, s.c_str(), mutated_size); // copy the mutated data
|
||||
// Assign the mutated data and return mutated_size
|
||||
*out_buf = mutated_out;
|
||||
return mutated_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deinitialize everything
|
||||
*
|
||||
* @param data The data ptr from afl_custom_init
|
||||
*/
|
||||
extern "C" void afl_custom_deinit(void *data) {
|
||||
// Honestly I don't know what to do with this...
|
||||
return;
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
#include <src/mutator.h>
|
||||
#include "test.pb.h"
|
||||
|
||||
class MyMutator : public protobuf_mutator::Mutator {
|
||||
};
|
7
custom_mutators/libprotobuf-mutator-example/test.proto
Normal file
7
custom_mutators/libprotobuf-mutator-example/test.proto
Normal file
@ -0,0 +1,7 @@
|
||||
syntax = "proto2";
|
||||
|
||||
message TEST {
|
||||
required uint32 a = 1;
|
||||
required string b = 2;
|
||||
}
|
||||
|
17
custom_mutators/libprotobuf-mutator-example/vuln.c
Normal file
17
custom_mutators/libprotobuf-mutator-example/vuln.c
Normal file
@ -0,0 +1,17 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char str[100]={};
|
||||
read(0, str, 100);
|
||||
int *ptr = NULL;
|
||||
if( str[0] == '\x02' || str[0] == '\xe8') {
|
||||
*ptr = 123;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -37,10 +37,6 @@
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include "android-ashmem.h"
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#include "types.h"
|
||||
#include "debug.h"
|
||||
|
@ -1,112 +1,81 @@
|
||||
/*
|
||||
american fuzzy lop++ - android shared memory compatibility layer
|
||||
----------------------------------------------------------------
|
||||
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
This header re-defines the shared memory routines used by AFL++
|
||||
using the Andoid API.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#ifndef _ANDROID_ASHMEM_H
|
||||
#define _ANDROID_ASHMEM_H
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <fcntl.h>
|
||||
#include <linux/ashmem.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <linux/shm.h>
|
||||
#include <linux/ashmem.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#if __ANDROID_API__ >= 26
|
||||
#define shmat bionic_shmat
|
||||
#define shmctl bionic_shmctl
|
||||
#define shmdt bionic_shmdt
|
||||
#define shmget bionic_shmget
|
||||
#endif
|
||||
#include <sys/shm.h>
|
||||
#undef shmat
|
||||
#undef shmctl
|
||||
#undef shmdt
|
||||
#undef shmget
|
||||
#include <stdio.h>
|
||||
|
||||
#if __ANDROID_API__ >= 26
|
||||
#define shmat bionic_shmat
|
||||
#define shmctl bionic_shmctl
|
||||
#define shmdt bionic_shmdt
|
||||
#define shmget bionic_shmget
|
||||
#endif
|
||||
|
||||
#include <sys/shm.h>
|
||||
#undef shmat
|
||||
#undef shmctl
|
||||
#undef shmdt
|
||||
#undef shmget
|
||||
#include <stdio.h>
|
||||
|
||||
#define ASHMEM_DEVICE "/dev/ashmem"
|
||||
|
||||
static inline int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) {
|
||||
#define ASHMEM_DEVICE "/dev/ashmem"
|
||||
|
||||
int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) {
|
||||
int ret = 0;
|
||||
if (__cmd == IPC_RMID) {
|
||||
|
||||
int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL);
|
||||
struct ashmem_pin pin = {0, (unsigned int)length};
|
||||
int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL);
|
||||
struct ashmem_pin pin = {0, length};
|
||||
ret = ioctl(__shmid, ASHMEM_UNPIN, &pin);
|
||||
close(__shmid);
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static inline int shmget(key_t __key, size_t __size, int __shmflg) {
|
||||
|
||||
(void)__shmflg;
|
||||
int fd, ret;
|
||||
int shmget(key_t __key, size_t __size, int __shmflg) {
|
||||
(void) __shmflg;
|
||||
int fd, ret;
|
||||
char ourkey[11];
|
||||
|
||||
fd = open(ASHMEM_DEVICE, O_RDWR);
|
||||
if (fd < 0) return fd;
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
sprintf(ourkey, "%d", __key);
|
||||
ret = ioctl(fd, ASHMEM_SET_NAME, ourkey);
|
||||
if (ret < 0) goto error;
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = ioctl(fd, ASHMEM_SET_SIZE, __size);
|
||||
if (ret < 0) goto error;
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
return fd;
|
||||
|
||||
error:
|
||||
close(fd);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static inline void *shmat(int __shmid, const void *__shmaddr, int __shmflg) {
|
||||
|
||||
(void)__shmflg;
|
||||
int size;
|
||||
void *shmat(int __shmid, const void *__shmaddr, int __shmflg) {
|
||||
(void) __shmflg;
|
||||
int size;
|
||||
void *ptr;
|
||||
|
||||
size = ioctl(__shmid, ASHMEM_GET_SIZE, NULL);
|
||||
if (size < 0) { return NULL; }
|
||||
if (size < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, __shmid, 0);
|
||||
if (ptr == MAP_FAILED) { return NULL; }
|
||||
if (ptr == MAP_FAILED) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
|
||||
}
|
||||
|
||||
#endif /* __ANDROID__ */
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !_ANDROID_ASHMEM_H */
|
||||
#endif /* !__ANDROID__ */
|
||||
|
@ -26,9 +26,6 @@
|
||||
|
||||
#define AFL_MAIN
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include "android-ashmem.h"
|
||||
#endif
|
||||
#include "config.h"
|
||||
#include "types.h"
|
||||
#include "debug.h"
|
||||
|
14
src/afl-cc.c
14
src/afl-cc.c
@ -586,6 +586,9 @@ static void edit_params(u32 argc, char **argv, char **envp) {
|
||||
if (instrument_mode == INSTRUMENT_PCGUARD) {
|
||||
|
||||
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
|
||||
#ifdef __ANDROID__
|
||||
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
|
||||
#else
|
||||
if (have_instr_list) {
|
||||
|
||||
if (!be_quiet)
|
||||
@ -605,6 +608,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#else
|
||||
#if LLVM_MAJOR >= 4
|
||||
if (!be_quiet)
|
||||
@ -1034,6 +1038,10 @@ int main(int argc, char **argv, char **envp) {
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
have_llvm = 1;
|
||||
#endif
|
||||
|
||||
if ((ptr = find_object("afl-gcc-pass.so", argv[0])) != NULL) {
|
||||
|
||||
have_gcc_plugin = 1;
|
||||
@ -1807,11 +1815,8 @@ int main(int argc, char **argv, char **envp) {
|
||||
if (!be_quiet && cmplog_mode)
|
||||
printf("CmpLog mode by <andreafioraldi@gmail.com>\n");
|
||||
|
||||
#ifdef __ANDROID__
|
||||
ptr = find_object("afl-compiler-rt.so", argv[0]);
|
||||
#else
|
||||
#ifndef __ANDROID__
|
||||
ptr = find_object("afl-compiler-rt.o", argv[0]);
|
||||
#endif
|
||||
|
||||
if (!ptr) {
|
||||
|
||||
@ -1824,6 +1829,7 @@ int main(int argc, char **argv, char **envp) {
|
||||
if (debug) { DEBUGF("rt=%s obj_path=%s\n", ptr, obj_path); }
|
||||
|
||||
ck_free(ptr);
|
||||
#endif
|
||||
|
||||
edit_params(argc, argv, envp);
|
||||
|
||||
|
@ -141,7 +141,10 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
|
||||
struct custom_mutator *mutator = ck_alloc(sizeof(struct custom_mutator));
|
||||
|
||||
mutator->name = fn;
|
||||
mutator->name_short = strrchr(fn, '/') + 1;
|
||||
if (memchr(fn, '/', strlen(fn)))
|
||||
mutator->name_short = strrchr(fn, '/') + 1;
|
||||
else
|
||||
mutator->name_short = strdup(fn);
|
||||
ACTF("Loading custom mutator library from '%s'...", fn);
|
||||
|
||||
dh = dlopen(fn, RTLD_NOW);
|
||||
|
@ -58,7 +58,11 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) {
|
||||
for (i = 0; i < argc; ++i) {
|
||||
|
||||
if (i) fprintf(f, " ");
|
||||
#ifdef __ANDROID__
|
||||
if (memchr(argv[i], '\'', sizeof(argv[i]))) {
|
||||
#else
|
||||
if (index(argv[i], '\'')) {
|
||||
#endif
|
||||
|
||||
fprintf(f, "'");
|
||||
for (j = 0; j < strlen(argv[i]); j++)
|
||||
|
@ -35,9 +35,6 @@
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include "android-ashmem.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
@ -31,9 +31,6 @@
|
||||
|
||||
#define AFL_MAIN
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include "android-ashmem.h"
|
||||
#endif
|
||||
#include "config.h"
|
||||
#include "types.h"
|
||||
#include "debug.h"
|
||||
|
@ -29,10 +29,6 @@
|
||||
|
||||
#define AFL_MAIN
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include "android-ashmem.h"
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#include "types.h"
|
||||
#include "debug.h"
|
||||
|
@ -153,7 +153,7 @@ static int enumerate_ranges(const GumRangeDetails *details,
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
#ifndef __APPLE__
|
||||
(void)personality(ADDR_NO_RANDOMIZE); // disable ASLR
|
||||
@ -164,105 +164,140 @@ int main() {
|
||||
// If there is just one function, then there is nothing to change
|
||||
// or add here.
|
||||
|
||||
void *dl = dlopen(TARGET_LIBRARY, RTLD_LAZY);
|
||||
void *dl = NULL;
|
||||
if (argc > 2) {
|
||||
dl = dlopen(argv[1], RTLD_LAZY);
|
||||
} else {
|
||||
dl = dlopen(TARGET_LIBRARY, RTLD_LAZY);
|
||||
}
|
||||
if (!dl) {
|
||||
|
||||
fprintf(stderr, "Could not load %s\n", TARGET_LIBRARY);
|
||||
if (argc > 2)
|
||||
fprintf(stderr, "Could not load %s\n", argv[1]);
|
||||
else
|
||||
fprintf(stderr, "Could not load %s\n", TARGET_LIBRARY);
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
if (!(o_function = dlsym(dl, TARGET_FUNCTION))) {
|
||||
if (argc > 2)
|
||||
o_function = dlsym(dl, argv[2]);
|
||||
else
|
||||
o_function = dlsym(dl, TARGET_FUNCTION);
|
||||
if (!o_function) {
|
||||
|
||||
fprintf(stderr, "Could not find function %s\n", TARGET_FUNCTION);
|
||||
if (argc > 2)
|
||||
fprintf(stderr, "Could not find function %s\n", argv[2]);
|
||||
else
|
||||
fprintf(stderr, "Could not find function %s\n", TARGET_FUNCTION);
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
// END STEP 2
|
||||
|
||||
gum_init_embedded();
|
||||
if (!gum_stalker_is_supported()) {
|
||||
|
||||
gum_deinit_embedded();
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
GumStalker *stalker = gum_stalker_new();
|
||||
|
||||
GumAddress base_address = gum_module_find_base_address(TARGET_LIBRARY);
|
||||
GumMemoryRange code_range;
|
||||
gum_module_enumerate_ranges(TARGET_LIBRARY, GUM_PAGE_RX, enumerate_ranges,
|
||||
&code_range);
|
||||
|
||||
guint64 code_start = code_range.base_address;
|
||||
guint64 code_end = code_range.base_address + code_range.size;
|
||||
range_t instr_range = {0, code_start, code_end};
|
||||
|
||||
printf("Frida instrumentation: base=0x%lx instrumenting=0x%lx-%lx\n",
|
||||
base_address, code_start, code_end);
|
||||
if (!code_start || !code_end) {
|
||||
|
||||
fprintf(stderr, "Error: no valid memory address found for %s\n",
|
||||
TARGET_LIBRARY);
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
GumStalkerTransformer *transformer =
|
||||
gum_stalker_transformer_make_from_callback(instr_basic_block,
|
||||
&instr_range, NULL);
|
||||
|
||||
// to ensure that the signatures are not optimized out
|
||||
memcpy(__afl_area_ptr, (void *)AFL_PERSISTENT, sizeof(AFL_PERSISTENT) + 1);
|
||||
memcpy(__afl_area_ptr + 32, (void *)AFL_DEFER_FORKSVR,
|
||||
sizeof(AFL_DEFER_FORKSVR) + 1);
|
||||
__afl_manual_init();
|
||||
|
||||
//
|
||||
// any expensive target library initialization that has to be done just once
|
||||
// - put that here
|
||||
//
|
||||
|
||||
gum_stalker_follow_me(stalker, transformer, NULL);
|
||||
|
||||
while (__afl_persistent_loop(UINT32_MAX) != 0) {
|
||||
|
||||
previous_pc = 0; // Required!
|
||||
|
||||
#ifdef _DEBUG
|
||||
fprintf(stderr, "CLIENT crc: %016llx len: %u\n",
|
||||
hash64(__afl_fuzz_ptr, *__afl_fuzz_len), *__afl_fuzz_len);
|
||||
fprintf(stderr, "RECV:");
|
||||
for (int i = 0; i < *__afl_fuzz_len; i++)
|
||||
fprintf(stderr, "%02x", __afl_fuzz_ptr[i]);
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
|
||||
// STEP 3: ensure the minimum length is present and setup the target
|
||||
// function to fuzz.
|
||||
|
||||
if (*__afl_fuzz_len > 0) {
|
||||
|
||||
__afl_fuzz_ptr[*__afl_fuzz_len] = 0; // if you need to null terminate
|
||||
(*o_function)(__afl_fuzz_ptr, *__afl_fuzz_len);
|
||||
|
||||
if (!getenv("AFL_FRIDA_TEST_INPUT")) {
|
||||
gum_init_embedded();
|
||||
if (!gum_stalker_is_supported()) {
|
||||
|
||||
gum_deinit_embedded();
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
GumStalker *stalker = gum_stalker_new();
|
||||
|
||||
GumAddress base_address;
|
||||
if (argc > 2)
|
||||
base_address = gum_module_find_base_address(argv[1]);
|
||||
else
|
||||
base_address = gum_module_find_base_address(TARGET_LIBRARY);
|
||||
GumMemoryRange code_range;
|
||||
if (argc > 2)
|
||||
gum_module_enumerate_ranges(argv[1], GUM_PAGE_RX, enumerate_ranges,
|
||||
&code_range);
|
||||
else
|
||||
gum_module_enumerate_ranges(TARGET_LIBRARY, GUM_PAGE_RX, enumerate_ranges,
|
||||
&code_range);
|
||||
|
||||
guint64 code_start = code_range.base_address;
|
||||
guint64 code_end = code_range.base_address + code_range.size;
|
||||
range_t instr_range = {0, code_start, code_end};
|
||||
|
||||
printf("Frida instrumentation: base=0x%lx instrumenting=0x%lx-%lx\n",
|
||||
base_address, code_start, code_end);
|
||||
if (!code_start || !code_end) {
|
||||
|
||||
if (argc > 2)
|
||||
fprintf(stderr, "Error: no valid memory address found for %s\n",
|
||||
argv[1]);
|
||||
else
|
||||
fprintf(stderr, "Error: no valid memory address found for %s\n",
|
||||
TARGET_LIBRARY);
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
GumStalkerTransformer *transformer =
|
||||
gum_stalker_transformer_make_from_callback(instr_basic_block,
|
||||
&instr_range, NULL);
|
||||
|
||||
// to ensure that the signatures are not optimized out
|
||||
memcpy(__afl_area_ptr, (void *)AFL_PERSISTENT, sizeof(AFL_PERSISTENT) + 1);
|
||||
memcpy(__afl_area_ptr + 32, (void *)AFL_DEFER_FORKSVR,
|
||||
sizeof(AFL_DEFER_FORKSVR) + 1);
|
||||
__afl_manual_init();
|
||||
|
||||
//
|
||||
// any expensive target library initialization that has to be done just once
|
||||
// - put that here
|
||||
//
|
||||
|
||||
gum_stalker_follow_me(stalker, transformer, NULL);
|
||||
|
||||
while (__afl_persistent_loop(UINT32_MAX) != 0) {
|
||||
|
||||
previous_pc = 0; // Required!
|
||||
|
||||
#ifdef _DEBUG
|
||||
fprintf(stderr, "CLIENT crc: %016llx len: %u\n",
|
||||
hash64(__afl_fuzz_ptr, *__afl_fuzz_len), *__afl_fuzz_len);
|
||||
fprintf(stderr, "RECV:");
|
||||
for (int i = 0; i < *__afl_fuzz_len; i++)
|
||||
fprintf(stderr, "%02x", __afl_fuzz_ptr[i]);
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
|
||||
// STEP 3: ensure the minimum length is present and setup the target
|
||||
// function to fuzz.
|
||||
|
||||
if (*__afl_fuzz_len > 0) {
|
||||
|
||||
__afl_fuzz_ptr[*__afl_fuzz_len] = 0; // if you need to null terminate
|
||||
(*o_function)(__afl_fuzz_ptr, *__afl_fuzz_len);
|
||||
|
||||
}
|
||||
|
||||
// END STEP 3
|
||||
|
||||
}
|
||||
|
||||
gum_stalker_unfollow_me(stalker);
|
||||
|
||||
while (gum_stalker_garbage_collect(stalker))
|
||||
g_usleep(10000);
|
||||
|
||||
g_object_unref(stalker);
|
||||
g_object_unref(transformer);
|
||||
gum_deinit_embedded();
|
||||
|
||||
// END STEP 3
|
||||
|
||||
} else {
|
||||
char buf[8*1024] = {0};
|
||||
int count = read(0, buf, sizeof(buf));
|
||||
buf[8*1024-1] = '\0';
|
||||
(*o_function)(buf, count);
|
||||
}
|
||||
|
||||
gum_stalker_unfollow_me(stalker);
|
||||
|
||||
while (gum_stalker_garbage_collect(stalker))
|
||||
g_usleep(10000);
|
||||
|
||||
g_object_unref(stalker);
|
||||
g_object_unref(transformer);
|
||||
gum_deinit_embedded();
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
1
utils/afl_frida/android/README.md
Normal file
1
utils/afl_frida/android/README.md
Normal file
@ -0,0 +1 @@
|
||||
For android, frida-gum package (ex. https://github.com/frida/frida/releases/download/14.2.6/frida-gum-devkit-14.2.6-android-arm64.tar.xz) is needed to be extracted in the directory.
|
130
utils/afl_frida/android/frida-gum-example.c
Normal file
130
utils/afl_frida/android/frida-gum-example.c
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Compile with:
|
||||
*
|
||||
* clang -fPIC -DANDROID -ffunction-sections -fdata-sections -Os -pipe -g3 frida-gum-example.c -o frida-gum-example -L. -lfrida-gum -llog -ldl -lm -pthread -Wl,--gc-sections,-z,noexecstack,-z,relro,-z,now -fuse-ld=gold -fuse-ld=gold -Wl,--icf=all
|
||||
*
|
||||
* Visit https://frida.re to learn more about Frida.
|
||||
*/
|
||||
|
||||
#include "frida-gum.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
typedef struct _ExampleListener ExampleListener;
|
||||
typedef enum _ExampleHookId ExampleHookId;
|
||||
|
||||
struct _ExampleListener
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
guint num_calls;
|
||||
};
|
||||
|
||||
enum _ExampleHookId
|
||||
{
|
||||
EXAMPLE_HOOK_OPEN,
|
||||
EXAMPLE_HOOK_CLOSE
|
||||
};
|
||||
|
||||
static void example_listener_iface_init (gpointer g_iface, gpointer iface_data);
|
||||
|
||||
#define EXAMPLE_TYPE_LISTENER (example_listener_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (ExampleListener, example_listener, EXAMPLE, LISTENER, GObject)
|
||||
G_DEFINE_TYPE_EXTENDED (ExampleListener,
|
||||
example_listener,
|
||||
G_TYPE_OBJECT,
|
||||
0,
|
||||
G_IMPLEMENT_INTERFACE (GUM_TYPE_INVOCATION_LISTENER,
|
||||
example_listener_iface_init))
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char * argv[])
|
||||
{
|
||||
GumInterceptor * interceptor;
|
||||
GumInvocationListener * listener;
|
||||
|
||||
gum_init_embedded ();
|
||||
|
||||
interceptor = gum_interceptor_obtain ();
|
||||
listener = g_object_new (EXAMPLE_TYPE_LISTENER, NULL);
|
||||
|
||||
gum_interceptor_begin_transaction (interceptor);
|
||||
gum_interceptor_attach (interceptor,
|
||||
GSIZE_TO_POINTER (gum_module_find_export_by_name (NULL, "open")),
|
||||
listener,
|
||||
GSIZE_TO_POINTER (EXAMPLE_HOOK_OPEN));
|
||||
gum_interceptor_attach (interceptor,
|
||||
GSIZE_TO_POINTER (gum_module_find_export_by_name (NULL, "close")),
|
||||
listener,
|
||||
GSIZE_TO_POINTER (EXAMPLE_HOOK_CLOSE));
|
||||
gum_interceptor_end_transaction (interceptor);
|
||||
|
||||
close (open ("/etc/hosts", O_RDONLY));
|
||||
close (open ("/etc/fstab", O_RDONLY));
|
||||
|
||||
g_print ("[*] listener got %u calls\n", EXAMPLE_LISTENER (listener)->num_calls);
|
||||
|
||||
gum_interceptor_detach (interceptor, listener);
|
||||
|
||||
close (open ("/etc/hosts", O_RDONLY));
|
||||
close (open ("/etc/fstab", O_RDONLY));
|
||||
|
||||
g_print ("[*] listener still has %u calls\n", EXAMPLE_LISTENER (listener)->num_calls);
|
||||
|
||||
g_object_unref (listener);
|
||||
g_object_unref (interceptor);
|
||||
|
||||
gum_deinit_embedded ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
example_listener_on_enter (GumInvocationListener * listener,
|
||||
GumInvocationContext * ic)
|
||||
{
|
||||
ExampleListener * self = EXAMPLE_LISTENER (listener);
|
||||
ExampleHookId hook_id = GUM_IC_GET_FUNC_DATA (ic, ExampleHookId);
|
||||
|
||||
switch (hook_id)
|
||||
{
|
||||
case EXAMPLE_HOOK_OPEN:
|
||||
g_print ("[*] open(\"%s\")\n", (const gchar *) gum_invocation_context_get_nth_argument (ic, 0));
|
||||
break;
|
||||
case EXAMPLE_HOOK_CLOSE:
|
||||
g_print ("[*] close(%d)\n", GPOINTER_TO_INT (gum_invocation_context_get_nth_argument (ic, 0)));
|
||||
break;
|
||||
}
|
||||
|
||||
self->num_calls++;
|
||||
}
|
||||
|
||||
static void
|
||||
example_listener_on_leave (GumInvocationListener * listener,
|
||||
GumInvocationContext * ic)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
example_listener_class_init (ExampleListenerClass * klass)
|
||||
{
|
||||
(void) EXAMPLE_IS_LISTENER;
|
||||
(void) glib_autoptr_cleanup_ExampleListener;
|
||||
}
|
||||
|
||||
static void
|
||||
example_listener_iface_init (gpointer g_iface,
|
||||
gpointer iface_data)
|
||||
{
|
||||
GumInvocationListenerInterface * iface = g_iface;
|
||||
|
||||
iface->on_enter = example_listener_on_enter;
|
||||
iface->on_leave = example_listener_on_leave;
|
||||
}
|
||||
|
||||
static void
|
||||
example_listener_init (ExampleListener * self)
|
||||
{
|
||||
}
|
@ -24,10 +24,6 @@
|
||||
|
||||
#define AFL_MAIN
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include "android-ashmem.h"
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#include "types.h"
|
||||
#include "debug.h"
|
||||
|
Loading…
x
Reference in New Issue
Block a user