C++ Keylog Not Working Properly - c++

I'm trying to make a simple keylogger in C++ (for learning only) and it's not quite working how I would like it to. My goal is to have it write to a txt. Here's the code I have so far:
#include <iostream>
#include <fstream>
#include <conio.h>
#define LOG(x) logger << x;
int main()
{
using std::ofstream;
using std::fstream;
ofstream logger("logger.txt", fstream::app);
char ascii;
bool typing;
for(;;)
{
if(_kbhit())
{
typing = true;
ascii = getch();
while(typing == true) //tried 'if', doesn't work
{
LOG(ascii);
std::cout << ascii << std::endl;
//typing = false;
//break
//tried using the above two and didn't work
}
}
else typing = false;
}
logger.close();
}
When I make while(typing == true) continuous, the key that is pressed continuously gets printed, but at least it actually gets saved to the txt. When I try to make the loop stop after one keyboard click, nothing gets saved to the txt.
So what am I doing wrong? Thanks for any help!

The variable typing is never set to false, so it stays true and your loop continues. The following code works:
#include <fstream>
#include <conio.h>
int main()
{
std::ofstream logger("logger.txt", std::fstream::app);
for(char ascii; ascii != 3;)
{
ascii = getche();
logger << ascii;
}
return 0;
}
getche() prints the character typed, and 3 is the ASCII code for Ctrl+C. This logs all characters, even non-printable ones.
A few comments on your code:
Don't use macros (#define) unless you are substituting a large amount of code and using it often, or plan on changing what something does.
You use loops and variables where you don't need to. getch and related functions wait for input.
logger.close() is automatically done when logger goes out of scope and is destructed.
return 0 should be at the end of main. It's not necessary, but it is used to return to the OS and return 0, although automatically put in, is important to have in for clarity.
I personally don't use using statements. Just write out the namespace, it helps avoid collisions. That's why it's in a namespace.

Related

Why does _getch() still wait for enter instead of directly registering the user input?

I would like to use arrow keys user input without the user having to press enter every time after clicking the arrow. Therefore, I decided to use _getch(), which allegedly does exactly that. It is part of the conio.h library, which I imported. However, in my case,_getch() also requires the user to press enter and doesn't immediately register the user input, as it should've. How can I fix that? (I'm running on windows)
#include<iostream>
#include <conio.h>
using namespace std;
int main() {
int p = _getch();
cout<<p;
return 0;
}
For example, in the code above instead of directly printing the value of p after receiving input in the console, it still waits for enter to be pressed.
From Microsoft Docs:
When reading a function key or an arrow key, each function must be called twice; the first call returns 0 or 0xE0, and the second call returns the actual key code.
So a revised version of your code might look like this:
#include <iostream>
#include <conio.h>
int main() {
int p = 0;
while(p == 0 || p == 0xE0)
p = _getch();
std::cout << p;
return 0;
}

Always output to screen and allow redirection

I'm writing a small CLI application and I want to allow the user to redirect to a file while standard cout statements go to the output.txt file I want progress to always to go the screen.
./myApp > output.txt
10% complete
...
90% complete
Completed
Is this possible? How can I do it?
Thanks in advance!!
This will work even if both stdin and stdout have been redirected:
spectras#etherbee:~$ ./term
hello terminal!
spectras#etherbee:~$ ./term >/dev/null 2>&1
hello terminal!
The idea is to open the controlling terminal of the process directly, bypassing any redirection, like this:
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd = open("/dev/tty", O_WRONLY);
if (fd < 0 && errno != ENODEV) {
/* something went wrong */
return 1;
}
int hasTTY = (fd >= 0);
if (hasTTY) {
write(fd, "hello terminal!\n", 16);
}
return 0;
}
From man 4 tty:
The file /dev/tty is a character file with major number 5 and
minor number 0, usually of mode 0666 and owner.group root.tty. It is
a synonym for the controlling terminal of a process, if any.
If you're using C++, you might want to wrap the file descriptor into a custom streambuf, so you can use regular stream API on it. Alternately, some implementations of the C++ library offer extensions for that purpose. See here.
Or, if you don't care about getting the error code reliably, you could just std::ofstream terminal("/dev/tty").
Also as a design consideration if you do this, offering a quiet option to let the user turn off the writing to the terminal is a good idea.
Your process cannot know if the shell redirects the standard console output (std::cout) or not.
So you'll need another handle that lets you output to the terminal independently of that redirection.
As #Mark mentioned in their comment you could (ab-)use1 std::cerr to do that, along with some ASCII trickery to overwrite the current output line at the terminal (look at backspace characters: '\b').
1)Not to mention the mess printed at the terminal if the output isn't actually redirected.
You can write your progress indicators to the stderr stream. They will appear on the console if the user redirects stdout to a file.
For example:
fprintf(stderr, "10%% complete\n");
I figured out how to do it, even if the user redirects stderr. The following code gets the name of the current terminal and checks to see if our output is being redirected. It also has a my_write() function that allows you to write to both the terminal and the redirect file, if they've redirected stdout. You can use the my_write() function with the writetoterm variable where-ever you want to write something that you want to always be written to the terminal. The extern "C" has to be there, otherwise (on Debian 9 with GCC 6.3, anyway) the ttyname() function will just return NULL all the time.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <string>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <error.h>
#include <errno.h>
#include <sstream>
using std::string;
using std::fstream;
using std::cout;
using std::endl;
using std::cerr;
using std::stringstream;
void my_write(bool writetoterm, int termfd, string data)
{
if(writetoterm)
{
int result = write(termfd, data.c_str(), data.length());
if(result < data.length()){
cerr << "Error writing data to tty" << endl;
}
}
cout << data;
}
extern "C" {
char* GetTTY(int fd){
//printf("%s", ttyname(fd));
return ttyname(fd);
}
}
int main(int argc, char** argv){
getenv("TTY");
bool writetoterm = false;
struct stat sb = {};
if(!GetTTY(STDOUT_FILENO)){
//not a TTY
writetoterm = true;
}
int ttyfd = open(GetTTY(2), O_WRONLY);
if(ttyfd < 0){
//error in opening
cout << strerror(errno) << endl;
}
string data = "Hello, world!\n";
my_write(true, ttyfd, data);
int num_for_cout = 42;
stringstream ss;
ss << "If you need to use cout to send something that's not a string" << endl;
ss << "Do this: " << num_for_cout << endl;
my_write(writetoterm, ttyfd, ss.str().c_str());
return 0;
}
I found the official std:: method of handling this. There is another type... std::clog. This is specifically for information and always appears on the command line even though the user redirects the output of the program myProgram > out.txt.
Thanks this was great to see all the methods that this can be done.

Why My Language translator program in Visual C++ overwriting a file with nothing instead of the translation

I have developed a program for translating words in english to my native language.Everything works fine with no errors, except that I am not getting the desired output.
The program asks a user for an input file in which there are english words, then it will read the file and write the translations in my native language to an output file specified by the user. My problem is that the program writes nothing to the output file. I even chose a non-empty output file but all I have seen and understood is that the program overwrits all what are in the output file with nothing.
Please I am asking for someone's help in this difficult time because I have exhausted all my thinking.
Below is the complete program:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h >
#include <conio.h>
#include <iomanip>
#include <cctype>
#include <ctype.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
string Identifier;
ofstream outfile;
ifstream infile;
static string fname1, fname2;
char a = (char)infile.get();
void Display(){
outfile << "Nuna";
}
void gettok(){
Identifier = "";
if (isalnum(a)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
Identifier = a;
while (isalnum(a = (char)infile.get()))
Identifier += a;
while (isspace(a = (char)infile.get())){
if (Identifier == "Display"){
Display();
a = (char)infile.get();
}
}
}
}
int main(){
cout << "Enter name of the file to be translated ";
cin >> fname1;
cout << "Enter new file name";
cin >> fname2;
infile.open(fname1);
if (infile.fail())
{
cerr << " No such a file Exist";
exit(1);
}
outfile.open(fname2);
if (outfile.fail())
{
cerr << "Unable to create a file";
exit(1);
}
while (!infile.eof())
{
gettok();
}
infile.close();
outfile.close();
}
Thank you sir, #TimStraubinger for your guide.
1. Firstly, based on my definition of the Display() function, I just want the program to be in such a way that whenever the english word
Display is read in the input file, then the Display() function is called whose job is to write the translation of the word display as "Nuna" to the output file. I want to have a function for translating each english word as I have done for the word Display. But if there is a better way, help me out.
2. I used "char a = (char)infile.get() " because i want to declare "a" as global variable to be known and used by all of my functions and furthermore, I can't open a file outside the "main" function. So, I searched and thought of ways but all failed!
Please any one's help is welcomed!
There are many things wrong with this, here are my main suggestions. Firstly, your code is hard to read and confusing and defies lots of good convention. I recommend you follow a few textbook examples with C++ and learn to organize your code better so that we can better help you. As for your code, some more obvious problems are as follows:
char a = (char)infile.get()
Here, you're trying to access the file before it is opened. This needs to be called after infile is opened.
And to see something written to the file, you have the condition:
if (Identifier == "Display"){
Display();
a = (char)infile.get();
}
Why does the accumulator string, Identifier, need to have "Display" stored in order to write something to the file? (I highly recommend you find a better function name for Display(), which suggests you're writing something to the screen.) Also, inside the while (isspace(a = (char)infile.get())) loop, infile.get() will be called twice every loop, once to check the loop condition and once because you wrote it in additionally. This will cause every other character to be skipped in that loop.

ofstream overwriting stack variables

I'm working on a "threadpool" program for operating systems class. Essentially, files are extracted from a tar file and written to the disk, using a pool of 5 threads. Here's my thread code
#include <iostream>
#include <cstdlib>
using namespace std;
vector<Header*> headers;
vector<string> fileBlocks;
void* writeExtractedFiles(void* args)
{
bool hasFilesLeft = true;
ofstream outputFile;
while(hasFilesLeft)
{
pthread_mutex_lock(&mutex);
if(headers.size() != 0)
{
Header* hdr = headers.back();
headers.pop_back();
string fileBytes = fileBlocks.back();
fileBlocks.pop_back();
pthread_mutex_unlock(&mutex);
outputFile.open(hdr->fileName.c_str(), ios::app);
outputFile.rdbuf()->pubsetbuf(0,0);
fileBytes = fileBytes.substr(0, hdr->fileSize);
outputFile.put('0');
outputFile.close();
// This is a dummy object to check if the values are corrupted
Header* test0 = headers.back();
cout << "GRAWWR!";
//chown(hdr->fileName.c_str(), hdr->userId, hdr->groupId);
//chmod(hdr->fileName.c_str(), hdr->fileMode);
}
else
{
// We're done!
hasFilesLeft = false;
pthread_mutex_unlock(&mutex);
}
}
}
Note As of right now, I'm only testing it with a single thread. Obviously accessing the headers vector outside of my mutex would be counterproductive with multiple threads.
Problem is, the values for test0 are all messed up, super high numbers and nonsense for fileName. It seems like I'm overwriting my stack variables for some reason. When I comment out outputFile.close(); then my variable values aren't changed, but when I keep it, whether I actually write things to the file or not, things get wonky. I know there must be something I'm missing. I've tried getting rid of the buffer altogether, writing the file in a different place, anything I could think of. Any suggestions?
(I'm testing it on a Windows machine but it's being made for Linux)

how to detect arrow keys

I have created an application for detect pressing up and down key on keyboard
but nothing will be printed after pressing these keys.
I am using Visual C++ 2010
#include <iostream>
#include <conio.h>
using namespace std;
void main()
{
char x;
while(1)
{
x = getch();
if(x==0 || x==224)
{
x=getch();
if(x==80)
{
cout << "down"<<endl;
}
else if(x==72)
{
cout << "up"<<endl;
}
}//if x==0 || x=224
}//while1
}//main
What can be the problem?
Thanks
Just to answer why it isn't working: You are trying to use your user's input as unsigned. Your character variable is signed so the value is different than you are expecting. An unsigned 224 is a signed -32.
As far as your loop goes I'd suggest changing things to this.
void main()
{
char x;
while(true)
{
while(!kbhit()){}
x = getch();
if(x==0 || x==-32)
{
x=getch();
if(x==80)
{
cout << "down"<<endl;
}
else if(x==72)
{
cout << "up"<<endl;
}
}//if x==0 || x=224
}//while1
}//main
The program will still loop forever. Then the next loop, which I added, will continue to loop while there are no keys being pressed(buffered). Then getch() grabs the next char from the buffer. Now the problem you were running into, is that you had 224 (0xE0) which is technically correct. However in binary apparently -32 and 224 look the same.
I ran into a bit of the same issue at first, I couldn't figure out why my code wasn't hitting the correct code block and it was because the first character was actually -32 (0xE0)
Hope that is of some help, despite this being a really old question.
You can use the curses.h library. Read their guide and it should be very easy from there.
After you take input using getch() (store the input into an int, not a char), you can verify if it's one of the arrow keys using the defined keycodes. Just make sure you used keypad(stdscr, TRUE) before for the program to be able to recognize the arrow keys.
Us kbhit() to get Keyboard Arrow Keys