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
|
////
// THIS IS THE VALID PART
////
// store 1337 on the stack (inside the struct)
.text:0040123c c7 45 d0 39 05 00 00 MOV dword ptr [RBP + local_38],0x539
// store 1.234567 on the stack (inside the struct; indirection via XMM0 floating point register)
.text:00401243 f3 0f 10 05 dd 0f MOVSS XMM0,dword ptr [DAT_00402228] = 3F9E064Bh
00 00
.text:0040124b f3 0f 11 45 d4 MOVSS dword ptr [RBP + local_34],XMM0
// set integer value for %d in printf (ESI)
.text:00401250 8b 45 d0 MOV EAX,dword ptr [RBP + local_38]
.text:00401253 89 c6 MOV ESI,EAX
// format string address goes to EDI
.text:00401255 bf e1 21 40 00 MOV EDI,s_f.bank_account:_%d_004021e1 = "f.bank_account: %
// EAX is set to 0: zero floating point registers used in printf's arguments
.text:0040125a b8 00 00 00 00 MOV EAX,0x0
.text:0040125f e8 dc fd ff ff CALL <EXTERNAL>::printf int printf(char * __
// set float value for %f
// move float value from stack to XMM0
.text:00401264 f3 0f 10 45 d4 MOVSS XMM0,dword ptr [RBP + local_34]
// set XMM1 to 0
.text:00401269 66 0f ef c9 PXOR XMM1,XMM1
// convert singe precision float to double precision float (as printf expects double precision)
.text:0040126d f3 0f 5a c8 CVTSS2SD XMM1,XMM0
// move float through registers to finally be in XMM0 (if there are more float args they would go to XMM1, ...)
.text:00401271 66 48 0f 7e c8 MOVQ RAX,XMM1
.text:00401276 66 48 0f 6e c0 MOVQ XMM0,RAX
// format string address goes to EDI
.text:0040127b bf f5 21 40 00 MOV EDI,s_f.balance:_%f_004021f5 = "f.balance: %f\n"
// now EAX is set to 1 because we have one floating point argument passed to printf("...format string...", arg_1, arg_2, ...)
.text:00401280 b8 01 00 00 00 MOV EAX,0x1
// do the call to printf
.text:00401285 e8 b6 fd ff ff CALL <EXTERNAL>::printf int printf(char * __
////
// THIS IS THE INVALID PART
////
// NOW the casting happens in the code!
// get local_38 which is our integer! and move it to XMM0; at local_28 will be a pointer to local_38
// here it gets interesting, we prepare the float argument although we wanted to use it with %d
// mostly the same instructions as above (XMM2 instead of XMM1)
.text:0040128a 48 8d 45 d0 LEA RAX=>local_38,[RBP + -0x30]
.text:0040128e 48 89 45 e0 MOV qword ptr [RBP + local_28],RAX
.text:00401292 48 8b 45 e0 MOV RAX,qword ptr [RBP + local_28]
.text:00401296 f3 0f 10 00 MOVSS XMM0,dword ptr [RAX]=>local_38
.text:0040129a 66 0f ef d2 PXOR XMM2,XMM2
.text:0040129e f3 0f 5a d0 CVTSS2SD XMM2,XMM0
.text:004012a2 66 48 0f 7e d0 MOVQ RAX,XMM2
// integer will land in XMM0 finally but as a float representation
.text:004012a7 66 48 0f 6e c0 MOVQ XMM0,RAX
// format string address goes to EDI
.text:004012ac bf 04 22 40 00 MOV EDI,s_g.bank_account:_%d_00402204 = "g.bank_account: %
// now EAX is set to 1 because we have one floating point argument passed to printf("...format string...", arg_1, arg_2, ...)
.text:004012b1 b8 01 00 00 00 MOV EAX,0x1
// to the call to printf BUT
// although we prepared a floating point register (XMM0) printf sees that there is a %d and looks for it where an integer argument should be: in RSI/ESI (calling convention RDI, RSI, RDX, RCX, R8, R9; return value in RAX)
// SO: RSI is still the value that has been set above, more concrete, the value 0x4052a0 or 4215456 which is the address of a format string -> so completely unrelated to the data, we wanted to print
.text:004012b6 e8 85 fd ff ff CALL <EXTERNAL>::printf int printf(char * __
// here we will print an integer argument... but we used %f for floats
// now it is the other way arround: we copy the float value from the stack via EAX to ESI (normally for the first %d)
// BUT since we us %f in the format string printf will look for this value in XMM0 which in our case is set to 0 from previous operations (again unrelated to what we wanted to actually print)
.text:004012bb 48 8b 45 e0 MOV RAX,qword ptr [RBP + local_28]
.text:004012bf 8b 40 04 MOV EAX,dword ptr [RAX + local_34]
.text:004012c2 89 c6 MOV ESI,EAX
.text:004012c4 bf 18 22 40 00 MOV EDI,s_g.balance:_%f_00402218 = "g.balance: %f\n"
.text:004012c9 b8 00 00 00 00 MOV EAX,0x0
.text:004012ce e8 6d fd ff ff CALL <EXTERNAL>::printf int printf(char * __
|