Archive

Archive for the ‘OpenGL’ Category

Overriding dynamic library calls (function interposition)

August 18th, 2009 Wesley 7 comments

About function interposition

I was wondering how I could override dynamic library calls in Linux, and I came across this technique known as function interposition. It is a powerful technique that allows you to override dynamic library calls. It might sound dull, but it can be very, very useful. There are some memory trace tools that make use of this technique to work, but perhaps a cooler example is the OpenGL capture system which was created by nullkey: it can capture OpenGL frames by overriding certain OpenGL functions. Another example are cheat tools (wallhacks, aimbots) which also make use of this technique a lot.

Some background

While Googling (did I spell that right?) I came across this recent blog article which explains the background very well. I will quote it here:

First, some background. When a program that uses dynamic libraries is compiled, a list of undefined symbols is included in the binary, along with a list of libraries the program is linked with. There is no correspondence between the symbols and the libraries; the two lists just tell the loader which libraries to load and which symbols need to be resolved. At runtime, each symbol is resolved using the first library that provides it. This means that if we can get a library containing our wrapper functions to load before other libraries, the undefined symbols in the program will be resolved to our wrappers instead of the real functions.

So if we create a custom shared library which overrides some of the functions of the original library, our functions will be called instead of those of the original library.

How to do it

  • Write new functions which override existing functions
  • Compile the written code to a dynamic library that is linked to the dynamic linking interface library
  • Use the LD_PRELOAD environment variable when running an application to preload your custom library before all other dynamic libraries

The article by Jay Conrod has an example which shows you the basic implementation of a simple memory allocation tracer.

I have also cooked up an example myself. Because I’ve been busy learning more about OpenGL, I thought that it shouldn’t be too hard to create a wallhack for one of my favourite games: Soldier of Fortune 2 running in Wine. Just for testing purposes of course! I am no cheater :D It turned out to be relatively simple, although my first tries weren’t so very successful:

  • Epic fail – At least I know my library is used now.
  • Partial success – Disabling depth testing completely was only a partial success.
  • Success – A debugger can tell that players are drawn using glDrawElements(). By knowing the number of elements for each character, we can disable depth testing selectively.
Soldier of Fortune 2 wallhack example

Soldier of Fortune 2 wallhack example

For those of you who are interested in the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/*
    Simple wallhack example for Soldier of Fortune 2 (Wine) in Linux using function interposition

    This code snippet was written by Wesley Stessens (wesley@ubuntu.com)
    It is released in the Public Domain.

    Compilation: gcc -Wall -ansi -pedantic -shared -ldl -fPIC glhack.c -o glhack.so
    Usage: LD_PRELOAD=glhack.so wine game.exe
*/


#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdint.h>
#include <GL/gl.h>

/* Override the glDrawElements function */
GLAPI void GLAPIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) {
    /* Store the actual function in a static function pointer */
    static void (*glDrawElements_)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) = NULL;
    if (!glDrawElements_) {
        glDrawElements_ = (void(*)())(intptr_t)dlsym(RTLD_NEXT, "glDrawElements");
        puts("GLHack: glDrawElements call has been overridden");
    }

    /* Disable depth testing if the number of elements to draw is one of the following, which means a player is being drawn */
    /* To avoid abuse of this code by cheaters, I have changed all count constants below to VALUEX */
    if (count == VALUE1 || count == VALUE2 || count == VALUE3 || count == VALUE4)
        glDisable(GL_DEPTH_TEST);
    else
        glEnable(GL_DEPTH_TEST);
    glDrawElements_(mode, count, type, indices);
}

Interesting thought about multiplayer cheats and Wine

If anti-cheat tools would perform a sanity check of the OpenGL or DirectX DLL, they would only find the virtual DLL’s when a game is run in Wine, right? I’m wondering whether this sort of cheats can be made undetectable then. In a way I hope not, because cheaters are very annoying when you’re playing a game, but on the other hand, it would be an amazing technological achievement. Anyway, anti-cheat tools like PunkBuster don’t even work with Wine at the moment, so it might be a non-issue. What are your thoughts?

VN:F [1.6.3_896]
Rating: +4 (from 4 votes)
Categories: C, Linux, OpenGL, Programming

NeHe OpenGL lessons in Qt – Chapter 4

August 8th, 2009 Wesley No comments

As promised, the fourth chapter of the NeHe OpenGL lessons ported to make use of the Qt toolkit.

Fourth chapter: fog, fonts revisited, quadrics, particle engine, triangle strips, masking

In the fourth chapter you will learn a few cooler tricks. You will learn how to create good-looking fog effects and how certain objects can easily be constructed using quadrics. But the coolest thing that you will learn is how to create a simple particle engine (during lesson 19). To end off the chapter, you will learn how you can use masking to create partial transparency using bitmap textures.

Some minor modifications were made to improve the visual appearance of some of the lessons.

Videos and source code

This video shows the fog effect (lesson 16)
This video shows what you can achieve using quadrics (lesson 18)
This video shows the very cool particle engine that you will create! (lesson 19)
This video shows which effect masking has (lesson 20)
You can download the Qt 4 source code for this chapter here.

PS: The port of chapter 5 will take a while… I will be a bit busy the coming weeks, and the first lesson of chapter 5 is HUGE, so will require a lot of time to port.
Oh, and apparently I forgot to upload the source code for the third chapter. I have uploaded it now :)

VN:F [1.6.3_896]
Rating: +16 (from 16 votes)
Categories: C++, OpenGL, Programming, Qt

NeHe OpenGL lessons in Qt – Chapter 3

August 4th, 2009 Wesley 3 comments

Here is the third chapter of the NeHe OpenGL lessons ported to make use of the Qt toolkit.

Third chapter: waving texture, display lists and a lot of fonts

The third chapter starts off with a cool looking waving flag effect. After that you will learn about display lists. The last three lessons focus on different ways of displaying fonts. It is worth noting that rendering basic text at a chosen location, or translated into the OpenGL scene is extremely easy in Qt/OpenGL thanks to QGLWidget::renderText(). For other basic text effects (such as rotated, skewed or otherwise transformed text) you could also use QPainter directly on a QGLWidget. We won’t be doing this in our examples, but I just wanted to point out that it is possible.

I should also note that I have used an extra library in lesson 14 to display the 3D text. Qt itself is not able to display 3D text and doing this in a cross-platform way yourself would be rather hard. That’s why I have used the FTGL library for this. FTGL is a very easy to use cross-platform library with the sole purpose of rendering (3D) text in OpenGL.

Videos and source code

This video shows the waving flag effect (lesson 11)
This video shows the effect of using display lists (lesson 12)
This video shows rotated 3D text (lesson 14)
You can download the Qt 4 source code for this chapter here.

PS: You can expect chapter 4 in a few days :)

VN:F [1.6.3_896]
Rating: +14 (from 14 votes)
Categories: C++, OpenGL, Programming, Qt

NeHe OpenGL lessons in Qt – Chapter 1 and 2

August 3rd, 2009 Wesley 2 comments

Last week I have ported two chapters (the first 10 lessons) of the NeHe OpenGL lessons to make use of the Qt toolkit. You will notice that the code in Qt is much cleaner and simpler than the code in the original NeHe lessons. There is no need to create a rendering or device context yourself or anything like that, and input support like input from keyboard or mouse can simply be implemented by reimplementing one function. As an added bonus, your 3D applications will run on pretty much any platform.

First chapter: setting up an OpenGL window, polygons, colors, rotation, 3D shapes

After completing the first chapter, you will end up with a rotating pyramid and cube…

This video shows the end result (lesson 5).
You can download the Qt 4 source code for this chapter here.

Second chapter: texture mapping, texture filters, lighting, keyboard control, blending, moving bitmaps in 3D space, loading and moving through a 3D world

In the second chapter you will learn a lot about textures, among some other things. Sometimes we make use of QGLContext::bindTexture() to load an image, morph it into a texture and bind it to OpenGL all in one go. Other times we will do it manually because we want to specify the texture filter ourselves (but we do have QGLWidget::convertToGLFormat() which makes that easy as well). To handle keypresses we simply reimplement keyPressEvent(). To load in the 3D world from the file we make use of the excellent QFile and QTextStream classes. As an added bonus, we also make use of QGLWidget::renderText() to show the user what has changed when a key is pressed inside the OpenGL window. Lesson 9 also features a bonus fade-in effect for the revived stars. This makes the effect look much cooler.

This video shows the result of adding texture filters, lighting and keyboard control (lesson 7)
This video shows the result of all the above plus blending (lesson 8)
This video shows the result of moving bitmaps in 3D space (lesson 9)
This video shows the result of moving through a very simple 3D world (lesson 10)
You can download the Qt 4 source code for this chapter here.

The third and fourth chapter are almost complete as well, but I will give you the Qt ports of those chapters another time. Perhaps tomorrow.

VN:F [1.6.3_896]
Rating: +14 (from 14 votes)
Categories: C++, OpenGL, Programming, Qt

x86 Linux assembler

August 2nd, 2009 Wesley 4 comments

The last few days I’ve been looking at x86 Linux assembler programming. I think it’s important to know how the code which you write in higher-level languages gets translated to low-level instructions and in what way things like libc or the kernel are involved. With some knowledge of assembler you can not only directly optimize some slower operations by implementing them in low-level assembly and by utilizing specific processor features, but in general you will also learn in which ways you can optimize your software by just writing the high-level code a little bit different – by anticipating how your code will translate into low-level assembler instructions.

That was my motivation for trying to do a few things with the Netwide Assembler (NASM). The result is a simple demo which utilizes libc, GLUT and OpenGL to display a rotating pyramid and cube.

ogl.asm

compiled ogl.asm application running in Ubuntu 8.04

The resulting code can be viewed here:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
; OpenGL example in x86 Linux assembler / NASM using Glut
; Author: Wesley Stessens (wesley@ubuntu.com)
;
; OpenGL calls to create pyramid and cube are from Jeff Molofee's OpenGL tutorial
; See: http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=05
;
; Features:
;  - Calling C functions by cdecl conventions
;  - Using GLUT and OpenGL calls to perform 3D graphics
;  - Low-level framerate control
;
; Sample compile instructions:
; nasm -felf ogl.asm && ld -lglut -s -I/lib/ld-linux.so.2 -o ogl ogl.o
;
; This code is released as sample code in the public domain. Use it for whatever you want.
; Feel free to let me know if you found this code useful in any way.

; Glut
extern glutInit, glutInitDisplayMode, glutInitWindowSize, glutInitWindowPosition
extern glutCreateWindow, glutMainLoop
extern glutDisplayFunc, glutIdleFunc, glutReshapeFunc, glutKeyboardFunc
extern glutSwapBuffers

; Glu
extern gluPerspective

; OpenGL
extern glClearColor, glClearDepth, glDepthFunc, glEnable, glShadeModel
extern glClear, glLoadIdentity, glMatrixMode, glViewport
extern glTranslatef, glRotatef, glBegin, glEnd, glVertex3f, glColor3f

; Needed for framerate control
extern usleep

; Macros
%macro _3call 4
    push dword %4
    push dword %3
    push dword %2
    call %1
    add esp, 12
%endmacro
%macro _4call 5
    push dword %5
    push dword %4
    push dword %3
    push dword %2
    call %1
    add esp, 16
%endmacro

section .data
    title: db 'OpenGL in x86 Linux assembler / NASM using Glut', 0
    ; Data for FP math with 4 bytes
    n7: dd -7.0
    n6: dd -6.0
    n1p5: dd -1.5
    n1: dd -1.0
    p0p4: dd 0.4
    p0p5: dd 0.5
    p1: dd 1.0
    p1p5: dd 1.5
    p3: dd 3.0
    rottrm: dd 4.5
    rotsqm: dd -3.0

    ; Data for FP math with 8 bytes
    q0p1: dq 0.1
    q1: dq 1.0
    q45: dq 45.0
    q100: dq 100.0

    ; Data for framerate control
    mspf: dd 20000 ; ms per frame

section .bss
    ; Vars for rotation
    rottr: resd 1
    rotsq: resd 1
    ; Var for aspect ratio
    aspr: resq 1
    ; Vars for framerate control
    time: resd 2
    usecs: resd 1
    oldslp: resd 1

section .text
    global _start

fpsmanager:
    push eax
    push ebx
    push ecx
    push edx

    mov eax, 78 ; sys_gettimeofday
    mov ebx, time
    mov ecx, 0
    int 80h

    mov eax, [time + 4]
    sub eax, [usecs]
    mov ebx, [mspf]
    sub ebx, eax

    test eax, eax
    js keep_sleep
    test ebx, ebx
    js keep_sleep

    push ebx
    call usleep
    add esp, 4
    mov dword [oldslp], ebx
    jmp done_sleep

keep_sleep:
    push dword [oldslp]
    call usleep
    add esp, 4

done_sleep:
    mov eax, [time + 4]
    mov dword [usecs], eax

    pop edx
    pop ecx
    pop ebx
    pop eax
    ret

display:
    ; Prepare for drawing
    push dword 4100h ; GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT
    call glClear
    add esp, 4
    call glLoadIdentity

    ; Draw pyramid on the left of the screen
    _3call glTranslatef, [n1p5], 0, [n6]
    _4call glRotatef, [rottr], 0, [p1], 0
    push dword 9h ; GL_POLYGON
    call glBegin
    add esp, 4
    _3call glColor3f, [p1], 0, 0 ; Start drawing front face
    _3call glVertex3f, 0, [p1], 0
    _3call glColor3f, 0, [p1], 0
    _3call glVertex3f, [n1], [n1], [p1]
    _3call glColor3f, 0, 0, [p1]
    _3call glVertex3f, [p1], [n1], [p1]
    _3call glColor3f, [p1], 0, 0 ; Start drawing right face
    _3call glVertex3f, 0, [p1], 0
    _3call glColor3f, 0, 0, [p1]
    _3call glVertex3f, [p1], [n1], [p1]
    _3call glColor3f, 0, [p1], 0
    _3call glVertex3f, [p1], [n1], [n1]
    _3call glColor3f, [p1], 0, 0 ; Start drawing back face
    _3call glVertex3f, 0, [p1], 0
    _3call glColor3f, 0, [p1], 0
    _3call glVertex3f, [p1], [n1], [n1]
    _3call glColor3f, 0, 0, [p1]
    _3call glVertex3f, [n1], [n1], [n1]
    _3call glColor3f, [p1], 0, 0 ; Start drawing right face
    _3call glVertex3f, 0, [p1], 0
    _3call glColor3f, 0, 0, [p1]
    _3call glVertex3f, [n1], [n1], [n1]
    _3call glColor3f, 0, [p1], 0
    _3call glVertex3f, [n1], [n1], [p1]
    call glEnd

    ; Draw cube on the right of the screen
    call glLoadIdentity
    _3call glTranslatef, [p1p5], 0, [n7]
    _4call glRotatef, [rotsq], [p1], [p0p4], [p0p5]
    push dword 7h ; GL_QUADS
    call glBegin
    add esp, 4
    _3call glColor3f, 0, [p1], 0 ; Start drawing top face
    _3call glVertex3f, [p1], [p1], [n1]
    _3call glVertex3f, [n1], [p1], [n1]
    _3call glVertex3f, [n1], [p1], [p1]
    _3call glVertex3f, [p1], [p1], [p1]
    _3call glColor3f, [p1], [p0p5], 0 ; Start drawing bottom face
    _3call glVertex3f, [p1], [n1], [p1]
    _3call glVertex3f, [n1], [n1], [p1]
    _3call glVertex3f, [n1], [n1], [n1]
    _3call glVertex3f, [p1], [n1], [n1]
    _3call glColor3f, [p1], 0, 0 ; Start drawing front face
    _3call glVertex3f, [p1], [p1], [p1]
    _3call glVertex3f, [n1], [p1], [p1]
    _3call glVertex3f, [n1], [n1], [p1]
    _3call glVertex3f, [p1], [n1], [p1]
    _3call glColor3f, [p1], [p1], 0 ; Start drawing back face
    _3call glVertex3f, [p1], [n1], [n1]
    _3call glVertex3f, [n1], [n1], [n1]
    _3call glVertex3f, [n1], [p1], [n1]
    _3call glVertex3f, [p1], [p1], [n1]
    _3call glColor3f, 0, 0, [p1] ; Start drawing left face
    _3call glVertex3f, [n1], [p1], [p1]
    _3call glVertex3f, [n1], [p1], [n1]
    _3call glVertex3f, [n1], [n1], [n1]
    _3call glVertex3f, [n1], [n1], [p1]
    _3call glColor3f, [p1], 0, [p1] ; Start drawing right face
    _3call glVertex3f, [p1], [p1], [n1]
    _3call glVertex3f, [p1], [p1], [p1]
    _3call glVertex3f, [p1], [n1], [p1]
    _3call glVertex3f, [p1], [n1], [n1]
    call glEnd

    ; Update rotation
    fld dword [rottr]
    fadd dword [rottrm]
    fstp dword [rottr]
    fld dword [rotsq]
    fadd dword [rotsqm]
    fstp dword [rotsq]

    call glutSwapBuffers ; Swap buffers and display
    call fpsmanager ; Cap framerate if necessary
    ret

reshape:
    push ebp
    mov ebp, esp

    ; Prevent division by zero
    cmp dword [ebp+8], 0
    jne reshape_2
    inc dword [ebp+8]

reshape_2:
    fild dword [ebp+8]
    fidiv dword [ebp+12]
    fstp qword [aspr]

    push dword [ebp+12]
    push dword [ebp+8]
    push dword 0
    push dword 0
    call glViewport
    add esp, 16
    push dword 1701h; GL_PROJECTION
    call glMatrixMode
    add esp, 4
    call glLoadIdentity

    push dword [q100+4]
    push dword [q100]
    push dword [q0p1+4]
    push dword [q0p1]
    push dword [aspr+4]
    push dword [aspr]
    push dword [q45+4]
    push dword [q45]
    call gluPerspective
    add esp, 32

    push dword 1700h; GL_MODELVIEW
    call glMatrixMode
    add esp, 4

    pop ebp
    ret

keyhandler:
    ret

_start:
    ; Initialize glut
    push dword [esp+8]
    lea eax, [esp+8]
    push eax
    call glutInit
    add esp, 8
    push dword 1ah ; GLUT_RGBA|GLUT_DOUBLE|GLUT_ALPHA|GLUT_DEPTH
    call glutInitDisplayMode
    add esp, 4
    push dword 480
    push dword 640
    call glutInitWindowSize
    add esp, 8
    push dword 0
    push dword 0
    call glutInitWindowPosition
    add esp, 8

    ; Create window
    push title
    call glutCreateWindow
    add esp, 4

    ; Register functions
    push display
    call glutDisplayFunc
    call glutIdleFunc
    add esp, 4
    push reshape
    call glutReshapeFunc
    add esp, 4
    push keyhandler
    call glutKeyboardFunc
    add esp, 4

    ; Initialize OpenGL
    push dword 0
    push dword 0
    push dword 0
    push dword 0
    call glClearColor
    add esp, 16
    push dword [q1+4]
    push dword [q1]
    call glClearDepth
    add esp, 8
    push dword 203h; GL_LEQUAL
    call glDepthFunc
    add esp, 4
    push dword 0b71h; GL_DEPTH_TEST
    call glEnable
    add esp, 4
    push dword 1d01h; GL_SMOOTH
    call glShadeModel
    add esp, 4

    ; Frame rate cap initialization
    mov dword [oldslp], 0

    ; Enter main loop
    call glutMainLoop

    ; Exit (return with error code 0)
    mov eax, 1 ; sys_exit
    mov ebx, 0
    int 80h

I have also written two other smaller examples:
- marketing.asm is a really simple statistics application which calculates the ideal sample size given a few parameters
- alsawav.asm is a simple audio library which utilizes ALSA to play an unbuffered raw WAV/PCM sample

Please note that all these examples require an x86 Linux distribution. These examples will not work on any other operating system.

VN:F [1.6.3_896]
Rating: +6 (from 6 votes)