Simple yet not widely known trick. If your PE image has TLS callbacks, these callbacks can alter TLS table while executing. That means you can have one callback at the start, but if this callback adds some other callbacks, those will execute as well. There are few interesting possibilities, because PE loader doesn’t cache TLS table at the beginning of image load. 🙂
Sample code
Asm code |
SelectShow> |
; Self-modifying TLS callbacks
; This PE has only one TLS callback active at load time.
; However, the callback executes 0x10 times because it modifies TLS table before returning.
; Copyleft (c) Omega Red 2007
; fasm source
; 32-bit executable
format PE GUI
entry start
include '%fasminc%\win32a.inc'
include '%fasminc%\macro\proc32.inc'
;------------------------------------------------
section 'all' code data readable writable executable
start:
cinvoke printf, buf, fmt, [count]
invoke msgbox, 0, buf, t_main, 0
invoke exit, 0
;------------------------------------------------
tls_callback0:
inc dword [count]
cmp dword [count], 0x10 ; callback executed 0x10 times?
jge tls_end
; add another callback entry before returning
mov eax, [count]
mov dword [tls_callbacks+4*eax], tls_callback0
tls_end:
ret 0x0c
;------------------------------------------------
t_main db 'main',0
buf db 0x100 dup (0)
fmt db 'tls count: %d',0
count dd 0
;------------------------------------------------
; TLS directory
; !!! it's possible to change tls table WHILE IN TLS CALLBACK itself,
; fex you have only 1 tls at first, but this tls adds some more -
; those added will execute normally (table is not cached by loader)!
align 0x10
data 9 ; tls
dd 0 ;Raw Data Start VA
dd 0 ;Raw Data End VA
dd tls_index ;Address of Index
dd tls_callbacks ;Address of Callbacks
dd 0 ;Size of Zero Fill
dd 0 ;Reserved
tls_index dd 0
tls_callbacks: ; only one callback is present initially
dd tls_callback0 ; callback proc
dd 0xff dup (0) ; space reserved for more callback entries (but null at load time)
dd 0
end data
;------------------------------------------------
data import
library user, 'user32.dll',\
kernel, 'kernel32.dll'
import user,\
printf, 'wsprintfA',\
msgbox, 'MessageBoxA'
import kernel,\
exit, 'ExitProcess'
end data
|
~ by omeg on April 8, 2008.
assembly,
code,
windows internals
Leave a Reply