The following code works as expected in VS2012, Debug build:
#include <SDKDDKVer.h>
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <io.h>
#include <assert.h>
DWORD WINAPI childThread(LPVOID param) {
printf("I'm the child!\n"); fflush(stdout);
_isatty(-1);
//assert(1==0);
return 0;
}
void myInvalidParameterHandler(const wchar_t * expression, const wchar_t * function, const wchar_t * file, unsigned int line, uintptr_t pReserved) {
wprintf(L"%s:%i %s() - Invalid parameter [%s]", file, line, function, expression);
}
int _tmain(int argc, _TCHAR* argv[]) {
wprintf(L"Registering invalid parameter handler\n");
_invalid_parameter_handler newHandler = myInvalidParameterHandler;
_set_invalid_parameter_handler(newHandler);
printf("Testing.\n");
CreateThread(NULL, 0, childThread, NULL, 0, NULL);
// CreateThread(NULL, 0, childThread, NULL, 0, NULL);
printf("Thread(s) created, press Enter to exit.\n");
getchar();
return 0;
}
Parameter Validation will cause a "Abort/Retry/Ignore" popup from the childThread's _isatty(-1) and it stays around as long as necessary. If I hit "Ignore", then myInvalidParameterHandler is invoked, and the program runs until I hit Enter. All Good.
If the second CreateThread is uncommented so two Parameter Validation failures occur at once, then the program silently exits. Sometimes Abort/Retry/Ignore pops up, but it disappears within a second. The program never hangs around for main's getchar.
When run from within the debugger, it hits a breakpoint at:
msvcr110d.dll!_CrtDbgBreak() Line 87 C
msvcr110d.dll!_VCrtDbgReportW(int nRptType, void * returnAddress, const wchar_t * szFile, int nLine, const wchar_t * szModule, const wchar_t * szFormat, char * arglist) Line 506 C
msvcr110d.dll!_CrtDbgReportWV(int nRptType, void * returnAddress, const wchar_t * szFile, int nLine, const wchar_t * szModule, const wchar_t * szFormat, char * arglist) Line 262 C++
msvcr110d.dll!_CrtDbgReportW(int nRptType, const wchar_t * szFile, int nLine, const wchar_t * szModule, const wchar_t * szFormat, ...) Line 279 C++
msvcr110d.dll!_isatty(int fh) Line 41 C
assertTest.exe!childThread(void * param) Line 10 C++
This isn't a general problem of simultaneous assertions. If I swap commenting of _isatty(-1) and assert(1==0), then it does what I'd expect. We get two abort/retry/ignore popups, they hang around, and the main thread runs to completion.
Release builds don't have this problem, the invalid parameter handler is invoked for both threads and execution always continues.
For context, we had a long-running server process that was hitting _isatty(-1) in multiple threads and silently exiting. It's a problem that we've fixed, but this behavior made it very difficult to track down. I'm wondering if there's something that could be done to help.
I saw a question with similar behavior, but that was MinGW & was determined to be a compiler bug. I've verified that test works in VS2012.
Figured it out - somehow I'd gotten debugging disabled in my registry. They key Auto in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug was missing. Setting it to 1 caused the debugger named in the Debugger key, vsjitdebugger, to be invoked. Nothing disappears anymore!
Got the idea from http://support.microsoft.com/kb/188296 on disabling Watson.
Related
i want to get the value from an registry entry. Here is my code:
#include <atlbase.h>
#include <atlstr.h>
#include <iostream>
#define BUFFER 8192
int main()
{
char value[255];
DWORD BufferSize = BUFFER;
RegGetValue(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName", L"ComputerName", RRF_RT_REG_SZ, NULL, (PVOID)&value, &BufferSize);
std::cout << value << std::endl;
}
My Computer name is: DESKTOP-IGW3F.
But if i run my program my output is: D
I have no idea how to fix it...i hope you can help me.
The Win32 function RegGetValue() does not exist. It is only a preprocessor macro that will resolve to either RegGetValueA() or RegGetValueW() depending on your project settings. In your case, the macro resolves to RegGetValueW(), therefore it treats the registry value as a Unicode string (2 bytes per character). But you are using a char (1 byte per character) buffer to receive the Unicode data.
To make your code work, you need to either explicitly call RegGetValueA() instead, or change your buffer type from char to wchar_t. Either way, you should also check the return value of the function.
A working example could look like this:
#include <windows.h>
#include <iostream>
int main()
{
WCHAR value[255];
DWORD bufferSize = 255 * sizeof(WCHAR);
if (!RegGetValueW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName", L"ComputerName", RRF_RT_REG_SZ, NULL, value, &bufferSize))
{
std::wcout << value << std::endl;
}
}
Im trying to solve a binary exploitation problem from picoCTF, but I'm having trouble with gdb.
Here is the source code of the problem (I've commented some stuff to help me).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <wchar.h>
#include <locale.h>
#define BUF_SIZE 32
#define FLAG_LEN 64
#define KEY_LEN 4
void display_flag() {
char buf[FLAG_LEN];
FILE *f = fopen("flag.txt","r");
if (f == NULL) {
printf("'flag.txt' missing in the current directory!\n");
exit(0);
}
fgets(buf,FLAG_LEN,f);
puts(buf);
fflush(stdout);
}
// loads value into key, global variables ie not on stack
char key[KEY_LEN];
void read_canary() {
FILE *f = fopen("/problems/canary_3_257a2a2061c96a7fb8326dbbc04d0328/canary.txt","r");
if (f == NULL) {
printf("[ERROR]: Trying to Read Canary\n");
exit(0);
}
fread(key,sizeof(char),KEY_LEN,f);
fclose(f);
}
void vuln(){
char canary[KEY_LEN];
char buf[BUF_SIZE];
char user_len[BUF_SIZE];
int count;
int x = 0;
memcpy(canary,key,KEY_LEN); // copies "key" to canary, an array on the stack
printf("Please enter the length of the entry:\n> ");
while (x<BUF_SIZE) {
read(0,user_len+x,1);
if (user_len[x]=='\n') break;
x++;
}
sscanf(user_len,"%d",&count); // gives count the value of the len of user_len
printf("Input> ");
read(0,buf,count); // reads count bytes to buf from stdin
// compares canary (variable on stack) to key
// if overwriting need to get the value of key and maintain it, i assume its constant
if (memcmp(canary,key,KEY_LEN)) {
printf("*** Stack Smashing Detected *** : Canary Value Corrupt!\n");
exit(-1);
}
printf("Ok... Now Where's the Flag?\n");
fflush(stdout);
}
int main(int argc, char **argv){
setvbuf(stdout, NULL, _IONBF, 0);
int i;
gid_t gid = getegid();
setresgid(gid, gid, gid);
read_canary();
vuln();
return 0;
}
When I run this normally, with ./vuln, I get normal execution. But when I open it in gdb with gdb ./vuln and then run it with run, I get the [ERROR]: Trying to Read Canary message. Is this something that is intended to make the problem challenging? I don't want the solution, I just don't know if this is intended behaviour or a bug. Thanks
I don't want the solution, I just don't know if this is intended behaviour or a bug.
I am not sure whether you'll consider it intended behavior, but it's definitely not a bug.
Your ./vuln is a set-gid program. As such, it runs as group canary_3 when run outside of GDB, but as your group when run under GDB (for obvious security reason).
We can assume that the canary_3 group has read permissions on the canary.txt, but you don't.
P.S. If you printed strerror(errno) (as comments suggested), the resulting Permission denied. should have made the failure obvious.
I am currently trying to create a game using the windows console. It is supposed to be a raytracer (in the fashion of Wolfenstein 3D). I need to shade objects that are further away with different unicode characters called "shaded blocks".
The problem is, that these characters seem to bug out the Windows console. The "full block" looks as it is supposed to look:
However, when I use the "DARK SHADE" character, the console seems to bug out and displays this:
I then did some other testing. When pasting the character into the CMD, it is more slim, and taller:
However, when going into the consol properties and exiting it again, it squishes the blocks together, and adding masses of space characters after them (I added a dot to the end of the line so you can see where the spaces end):
I used Consolas with 16pt for all of them.
Can you tell me how to display these characters properly?
Thanks in advance.
[This is not an answer. It's a comment that requires code.]
Maybe try this:
#define UNICODE
#define NOMINMAX
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <iostream>
#include <string>
using namespace std;
namespace winapi {
HANDLE const std_output = GetStdHandle( STD_OUTPUT_HANDLE );
void write( wchar_t const* const s, int const n )
{
DWORD n_written;
WriteConsole( std_output, s, n, &n_written, 0 );
}
void write( wstring const& s )
{
write( s.c_str(), s.length() );
}
}
auto main()
-> int
{
wchar_t const light_shade = L'░';
wchar_t const medium_shade = L'▒';
wchar_t const dark_shade = L'▓';
winapi::write( wstring( 64, dark_shade ) + L'\n' );
}
I am working on an application, where if this certain error message is given, it is ignored:
[Oracle][ODBC][Ora]ORA-24338: statement handle not executed
My code for comparison is the following:
char Sqlstate[10];
long NativeErrorPtr;
char MessageText[1024];
long BufferLength=1024;
long TextLengthPtr;
SQLGetDiagRec(SQL_HANDLE_STMT,sqlc.g_hstmt,1,(SQLCHAR *) Sqlstate,(SQLINTEGER *) &NativeErrorPtr,
(SQLCHAR *) MessageText,(SQLSMALLINT) BufferLength,(SQLSMALLINT *) &TextLengthPtr);
success=false;
char* msg = MessageText;
char* oracleMsg = "[Oracle][ODBC][Ora]ORA-24338: statement handle not executed";
int i = strcmp(msg, oracleMsg);
I am getting i ==1. When I hover over both msg and oracleMsg they look exactly the same. Here is the copied text from each variable.
oracleMsg 0x00c1cd88 "[Oracle][ODBC][Ora]ORA-24338: statement handle not executed" char *
msg 0x0132d0a4 "[Oracle][ODBC][Ora]ORA-24338: statement handle not executed" char *
My problem must have been that it is not NULL-terminated. I followed ibre5041's advice and used if((strncmp(msg, oracleMsg, 55))== 0). This only compares the first 55 characters, which avoids the non NULL-terminated issue.
I've disabled line input with the following code:
DWORD dwConsoleMode;
GetConsoleMode(hStdIn, &dwConsoleMode);
dwConsoleMode ^= ENABLE_LINE_INPUT;
SetConsoleMode(hStdIn, dwConsoleMode);
Then I am calling ReadConsole in a loop...in a loop:
wchar_t cBuf;
while (1) {
/* Display Options */
do {
ReadConsole(hStdIn, &cBuf, 1, &dwNumRead, NULL);
} while (!iswdigit(cBuf));
putwchar(cBuf);
if (cBuf == L'0') break;
}
If I run the program and press 0 right away, it exists cleanly.
But if I press a bunch of keys, then press 0, when the program exists it crashes with:
Run-Time Check Failure #2 - Stack around the variable 'cBuf' was corrupted.
Why is this causing the stack to become corrupt? The code is simple, so I can't figure out what is wrong.
Little program that I can reproduce the problem with:
#include <windows.h>
#include <stdio.h>
int wmain(int argc, wchar_t *argv[])
{
DWORD dwNumRead;
wchar_t cBuf;
HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
DWORD dwConsoleMode;
GetConsoleMode(hStdIn, &dwConsoleMode);
dwConsoleMode ^= ENABLE_LINE_INPUT;
SetConsoleMode(hStdIn, dwConsoleMode);
while (true)
{
wprintf(L"\nEnter option: ");
do {
ReadConsoleW(hStdIn, &cBuf, 1, &dwNumRead, NULL);
} while (!iswdigit(cBuf));
putwchar(cBuf);
if (cBuf == L'0') break;
}
return 0;
}
You have to kind of mash your keyboard after you run it, then press 0, and it crashes with the stack corruption.
I also can't reproduce the problem every time, it takes a few tries.
I was running it under Visual Studio 2010, after creating a new empty console project and adding a file with that code.
As far as I can tell, this is a bug in Windows. Here is a slightly simpler program that demonstrates the problem:
#include <windows.h>
#include <crtdbg.h>
int wmain(int argc, wchar_t *argv[])
{
DWORD dwNumRead;
wchar_t cBuf[2];
cBuf[0] = cBuf[1] = 65535;
HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
SetConsoleMode(hStdIn, 0);
while (true)
{
_ASSERT(ReadConsoleW(hStdIn, &cBuf[0], 1, &dwNumRead, NULL));
_ASSERT(dwNumRead == 1);
_ASSERT(cBuf[1] == 65535);
Sleep(5000);
}
}
The sleep makes it a bit easier to trigger the issue, which occurs whenever more than one character is waiting at the time you call ReadConsoleW.
Looking at the content of cBuf[1] at the time the relevant assertion fails, it appears that ReadConsoleW is writing one extra byte at the end of the buffer.
The workaround is straightforward: make sure your buffer has at least one extra byte. In your case, use the first character of a two-character array.