

Show HN: Protecting Your Software Assets Using OpenGL - balls2you
https://stealthy.io/blog/201506.html

======
Mithaldu
How often do game assets get stolen? From my perspective copy-cats emulate the
style and the gameplay, but never outright steal assets; and players who do
piracy copy the game wholesale, so that encryption does nothing there. All
this kind of encryption does is mess with players who fancy customizing
things.

~~~
balls2you
From what I understand when I read the blog, they're trying to demonstrate
that you can use encryption/decryption on the GPU to create some form of DRM
unique to your application. Their previous blog cites they are into
researching some form of copy-protection systems.

As a once-upon-a-time iOS game dev, I can see it being used to handle In-App
purchases where your game will only progress after you have purchased
something and you get a key to decrypt the next level stuff. I can see it
being used in that way. That's why I posted it here. It seemed interesting.

------
ryandrake
The pirates will never pay for your software, and will always work around your
countermeasures, no matter how complicated or expensive they were to develop.
You're better off investing that money/effort into features that your actual
paying customers will pay more for.

~~~
balls2you
There are users who are pirates and then there are corporate pirates whose
businesses are built on copying and pirating popular games and making them
look professional. They are the real danger to indie devs not end users in
their mother's basement with no money in their pockets.

~~~
chii
> pirating popular games and making them look professional.

that's not pirating. you cannot own an idea (and i would say software patents
aren't good, despite their current prevalence). If the market demands good
looking games, i guess as an indie, you either just have to compete, or die
out like any other business would.

------
datenwolf
And what exactly is preventing me from injecting my custom libGL.so that hooks
onto the `glDraw…` calls, and downloads the current contents of the bound
textures using `glGetTexImage`?

Also OpenGL debugging tools _do_ exist and they work by hooking OpenGL and
using the OpenGL accessor functions to show you the contents of every OpenGL
object.

~~~
malkia
Like this (and this is not done to harm anyone) -
[http://www.wadeb.com/eq/](http://www.wadeb.com/eq/)

~~~
datenwolf
Kind of, but more rather like this:
[https://github.com/mazzoo/ogldump](https://github.com/mazzoo/ogldump)

Actually you'd not even need to inject a libGL.so at all. You could as well
just modify the PLT/GOT entries for the glDraw… functions to a dumper function
and then jmp to the actual glDraw… call. This could be done using the system
debugging APIs.

~~~
astrange
Many OpenGL implementations use a "virtual function" pattern where you look up
the driver's function pointers and call through that (AGL, CGL on OS X, WGL on
windows, probably more). It saves indirection when there's more than one
possible vendor but means you have to remember to wrap each of those when
doing interception.

~~~
datenwolf
Actually… no, unfortunately not (regarding the competence of the following I
suggest you look at my profile over at StackOverflow).

So the problem is twofold:

There are the OS-ABI OpenGL functions (i.e. OpenGL functions that are exposed
due to the ABI demands of the operating system) and there are the extended
functions. The Windows ABI mandates OpenGL-1.1, Linux used to be OpenGL-1.2
but the recently released LSB bumped that to 2.1. These ABI level functions
are expected (by the ABI) to be provided by the base system interface
libraries in the form of regular, non-hooked symbols.

And then there is the extended functionality, i.e. everything not covered by
the base system ABI, so modern OpenGL, and extension functions.

Windows and Linux treat the later case differently! In Windows extended
functions (pointers) must be assumed to be depending on the context the've
been gathered from. In Linux, namely the GLX specification it's explicitly
stated that extended functions' pointers are not tied to the context, but
rather the GLX interface.

Regarding OpenGL, or rather the typical implementations of it that leads to an
interesting problem: Dispatch. Every OpenGL function eventually must be
dispatched to the right driver. Using _indirect GLX_ this is easy, since
OpenGL calls are translated into GLX opcodes and transmitted via the GLX/X11
extension wire protocol; the X11 server then submits it to the graphics driver
proper (and honstly IMHO transmitting command buffers to a server is the only
proper way to do it: The benefits of _direct GL_ stem mostly from the fact
that the X11 protocol takes into account TCP transport; if we consider
localhost-only connections highly efficient RPC and zero-copy-SHM protocols
are possible).

But as soon as you hit direct GL it becomes a TLS context jump table
indirection mess. And only because the first implementers of OpenGL (who also
wrote the specification) were not fully aware of some of the leeway their own
words would provide them: *Nowhere in the OpenGL specs it is stated that
OpenGL functions shall reside in the global namespace. And nowhere in the
OpenGL specification it is forbidden, that actual OpenGL implementations add a
"context" 1st-parameter (akin to the implcit `this` of C++ class member
function) to every function call.

------
billconan
I think I can hook the opengl driver and get the shader source code and the
encryption key. and redo the decryption on cpu.

~~~
datenwolf
You don't have to go so far. Just inject a little bit of code into the game
process that calls a dumper function just before (or after, it doesn't really
matter) calls to `glDraw…` to dump out all the data of the currently bound
buffer objects and textures. glGetTexImage, glGetBufferData are your friends.

~~~
billconan
ya. this article doesn't make too much sense to me.

~~~
datenwolf
I think the people behind this come from a OpenGL-ES / WebGL background.
Coaxing data back out of OpenGL-ES / WebGL is a bit tricker compared to
original OpenGL. But only a little bit (you need a proxy FBO to retrieve
texture data; you can't write to buffer objects with shaders in ES/WebGL so
hooking glBufferData suffices).

~~~
billconan
I don't think it will be difficult. after all chromium and Angle are
opensource, you can hack chromium source code to get everything. plus,
javascript is already kinda open to steal. same to android. it is open.

on ios, it's harder. but shouldn't ios already encrypt all its apps?

~~~
microcolonel
Wouldn't matter, pretty sure you could just take the assets in the simulator.

~~~
balls2you
You're assuming the application that wants to protect its assets and other IP
will let you run it in a simulator which is not going to be the case.

