Sep.

C'est la rentrée et il est temps de retourner au charbon.
Après la gestion des pointeurs, dans la série «J'aime les trucs tordus», «piqure de rappel», etc.
bref, plus simplement pour montrer à nouveau l'étendue des possibilités de programmation du langage VB
au même titre que d'autres langages, voici un exemple connu du principe d'injection de code assembleur.

L' «injection» du code ASM est effectuée en détournant la fonction CallWindowProc de l'api User32
que l'on utilise habituellement lors de sous-classement.
Ici l'argument Function(lpPrevWndFunc) pointe directement sur une chaine de caractères qui sera exécutée comme une procédure à part entière ;
les autres paramètres servent principalement au retour des valeurs des registres.

L'exemple suivant utilise la même procédure de code ASM et retourne selon l'opcode défini :
la valeur du compteur de cycle (RDSTC) ou l'identification du CPU(si possible).

Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
 
            Private Declare Function CallWindowProcS Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As String, ByRef hwnd As Long, ByRef Msg As Long, ByRef wParam As Long, ByRef lParam As Long) As Long
 
            Public Function RDTSC()
                Dim a As Long, b As Long, c As Long, d As Long, ret As Variant
 
                ' Opcode: 0F 31
                a = &HF: b = &H31    
                Call_ASM a, b, c, d
 
                ret = (d * 4294967296#) + a     ' 2^32=4294967296#
 
                RDTSC = CDec(ret)
            End Function
 
 
            Public Function CPUID() As String
                Dim ret As Long, a As Long, b As Long, c As Long, d As Long
 
                ' Opcode: 0F A2
                a = &HF: b = &HA2        ' EAX=0:ID vendeur/1:Signature/2:Config/3:Serial'
                if Call_ASM(a, b, c, d, 1) then CPUID = Right("00000000" + Hex(d), 8) + Right("00000000" + Hex(a), 8)
            End Function
 
            Private Function Call_ASM(eax As Long, ebx As Long, ecx As Long, edx As Long, Optional ID As Long = 1)
                Dim Asm As String, a As Long, b As Long, c As Long, d As Long
 
                ' Sauvegarder les registres ESI, EBP
                Asm = Asm + Chr(&H56)                         '56                 push esi                    '
                Asm = Asm + Chr(&H55)                         '55                 push ebp                    '
                Asm = Asm + Chr(&H8B) + Chr(&HEC)             '8B EC              mov ebp,esp                 '
 
                ' Corps de procédure    
                Asm = Asm + Chr(&H8B) + Chr(&H75) + Chr(&HC)  '8B 75 0C           mov esi,dword ptr [ebp+0Ch] '    
                Asm = Asm + Chr(&H8B) + Chr(&H6)              '8B 06              mov eax,dword ptr [esi]     '
 
 
                Asm = Asm + Chr(eax) + Chr(ebx)               'Opcode                                  '
 
                Asm = Asm + Chr(&H8B) + Chr(&H75) + Chr(&HC)  '8B 75 0C           mov esi,dword ptr [ebp+0Ch] '
                Asm = Asm + Chr(&H89) + Chr(&H6)              '89 06              mov dword ptr [esi],eax     '
 
                Asm = Asm + Chr(&H8B) + Chr(&H75) + Chr(&H10) '8B 75 10           mov esi,dword ptr [ebp+10h] '
                Asm = Asm + Chr(&H89) + Chr(&H1E)             '89 1E              mov dword ptr [esi],ebx     '
                Asm = Asm + Chr(&H8B) + Chr(&H75) + Chr(&H14) '8B 75 14           mov esi,dword ptr [ebp+14h] '
                Asm = Asm + Chr(&H89) + Chr(&HE)              '89 0E              mov dword ptr [esi],ecx     '
                Asm = Asm + Chr(&H8B) + Chr(&H75) + Chr(&H18) '8B 75 18           mov esi,dword ptr [ebp+18h] '
                Asm = Asm + Chr(&H89) + Chr(&H16)             '89 16              mov dword ptr [esi],edx     '
 
 
                ' Restaurer les registres ESI, EBP
                Asm = Asm + Chr(&H5D)                         '5D                 pop ebp                     '
                Asm = Asm + Chr(&H5E)                         '5E                 pop esi                     '
 
                ' Fin
                Asm = Asm + Chr(&HC2) + Chr(&H10) + Chr(&H0)  'C2 10 00           ret 10h                     '
 
                eax = ID: ebx = 0: ecx = 0: edx = 0               
                Call_ASM = CallWindowProcS(Asm, eax, ebx, ecx, edx)
            End Function
La possibilité d'injecter du code assembleur ouvre toutes les portes imaginables et permet contrairement à l'idée reçue l'accès direct au Bios.
Evidemment cette méthode est inégalable en terme de vitesse comparativement à une méthode employant WMI (~50 000/1).