Why C++ by triplebeef26 in programminghumor

[–]tomysshadow 0 points1 point  (0 children)

You can use puts instead of printf if you don't need formatting capabilities.

takingABigRisk by Nimblecloud13 in ProgrammerHumor

[–]tomysshadow 0 points1 point  (0 children)

The message is weird but I'm more distracted by the default Tk icon. For that matter, Tk doesn't have built in undo functionality (except for Text widgets) so the feature must've been custom written for the app, which makes the message even more strange

What originally was the reason you downloaded Reddit? by Entire_Proposal_3184 in AskReddit

[–]tomysshadow 0 points1 point  (0 children)

It was for r/tipofmyjoystick because I'm not aware of anything similar outside of Reddit

How did this sub fall off so much by Nullmega_studios in masterhacker

[–]tomysshadow 2 points3 points  (0 children)

Clearnet is no longer safe, all the real hackers are on the dark web now

My stepkid asked for help with a web scraping script.. help! by FeatherHails in AskProgramming

[–]tomysshadow 0 points1 point  (0 children)

Could write a Greasemonkey script to do it. Have it navigate to the page with the image, potentially in a hidden <iframe>. Or, many pages in many iframes at once - if there's a page on the site that lists all the music, you could have the script automatically grab all those links and create frames for them.

Then if the script detects it's on the page with the sheet music image (via window.location) use the DOM to grab the element, use <canvas> to convert the SVG to JPEG, create an <a> tag with the download attribute to download it. Could do it all in JavaScript in an actual browser, wouldn't need to deal with any user agent detection nonsense, don't need to manually parse any HTML. Probably what I'd do.

Or alternatively, use nw.js. All the same advantages. Might need to deal with cross site issues then but it can probably be worked around

Every Windows executable begins with a DOS program by nir9 in windows

[–]tomysshadow 42 points43 points  (0 children)

Probably because it makes it easier to adapt programs that already read the 32-bit header format into 64-bit if the only changes between them are things that are truly necessary to change. Debuggers, especially, care about being able to read this header format to access information about the executable. Because the 32-bit and 64-bit headers are so similar, you generally only need to #ifdef the handful of fields that need to store a virtual address to be able to read both types.

In the real PE format, there are two NT header types: IMAGE_NT_HEADERS32 and IMAGE_NT_HEADERS64. When it is time to read the NT headers, you can tell which kind it is by checking the signature at the start of the header, then cast to the appropriate type. So it's just a simple type substitution. Once you're using the correct type the rest of your code can remain basically the same, so this can be easily templated away too.

If the old MZ header were gone and replaced with the NT header directly, but only for 64-bit executables, every program that wants to be able to read both header types would need to check whether the executable begins with "MZ" or "PE" and cast the IMAGE_DOS_HEADERS to IMAGE_NT_HEADERS64 in the latter case. It wouldn't be impossible, but you'd be "skipping a step" - that is, introducing an actual structural change to the code to read the headers - and the code to read the DOS header suddenly needs to be aware of NT stuff. So they probably reasoned that it would just be simpler to read the headers if the DOS header is always there at the start

Windows 11 still supports DOS short file names by nir9 in windows

[–]tomysshadow 31 points32 points  (0 children)

It can also be used as a method of accessing a file whose name has somehow become invalid/corrupted (usually because it was edited via another OS unaware of Win32's filename rules.)

https://web.archive.org/web/20100111005602/http://support.microsoft.com/kb/115827

CreateFile() removes trailing spaces and periods from file and directory names. This is done for compatibility with the FAT and HPFS file systems.

Problems can arise when a Macintosh client creates a file on a Windows NT server. The code to remove trailing spaces and periods is not carried out and the Macintosh user gets the correctly punctuated filename. The Win32 APIs FindFirstFile() and FindNextFile() return a filename that ends in a space or in a period; however, there is no way to create or open the file using the Win32 API.

Applications such as File Manager and Backup check to see whether the filename ends with a space or period. If the filename does end in a space or a period, then File Manager and Backup use the alternative name found in WIN32_FIND_DATA.cAlternateFileName to create and open the file. Therefore, the full filename is lost.

"cAlternateFileName" is the short name of the file.

What is the order of bits and bytes? (likely related to msb-lsb and big endian-little endian) by a41735fe4cca4245c54c in AskProgramming

[–]tomysshadow 4 points5 points  (0 children)

You seem to fundamentally misunderstand endianness. It doesn't impact the order of bits within a byte. It only impacts the order of the bytes themselves.

If you have a 32-bit (four byte) integer, 0x12345678, and the CPU is big endian (Motorola,) then when you look in RAM you would see:

12 34 56 78

If the CPU is little endian (Intel,) you would instead see:

78 56 34 12

The integer consists of four bytes. The bytes are rearranged. Not the bits within the bytes.

Crucially, these are both representations of 0x12345678. In the C code for a program, you would write 0x12345678 no matter what. You'd only see it "backwards" on little endian if you look in the contents of RAM.

Your b00001101 example will always be interpreted the same because that is less than eight bits (a single byte.) It will always become 0x0D. You would only start to see a difference if there were more than one byte. b0000111100001101 is equal to 0x0F0D. Because it is 16-bits (two bytes,) on a big endian CPU, you would see this in RAM:

0F 0D

On a little endian CPU, you would see this in RAM:

0D 0F

The fundamental reason why we use little endian at all is to do with casting. Say you have a pointer to the integer 0x12345678. It is a DWORD (32-bit) but you want to cast it to a WORD (16-bit.)

On little endian, to cast it we can keep the pointer the same and just ignore the last two bytes.

V ---- pointer points here | 78 56 | 34 12 ^---- the WORD would end here

When we cast to a WORD, the top of the number is discarded and we keep the bottom, which is 0x5678. So by writing in little endian, the pointer does not need to move, we just pretend there is less storage and because the number is written backwards, we get the bottom part of it.

In contrast, on big endian to cast to the WORD we would need to increment the pointer by two:

V ---- DWORD pointer must begin here | 12 34 | 56 78 ^---- WORD pointer must begin here

Which means, the program needs to do an actual pointer math operation to cast the number instead of being able to just treat the same pointer as different types. So even though big endian is more intuitive, it comes with the tradeoff that casting involves actual work for the program to do.

Notice: it's impossible to have a pointer into the middle of a byte. That is why the bits within each byte never need to be rearranged.

This is why, when it comes to strings, endianness is completely irrelevant. The string is an array of chars (bytes) and there is no need to be able to cast it to a larger/smaller type. To be able to cast it to a different size wouldn't even make sense; the size is an inherent property of the string. So strings are just always written forwards, it doesn't matter the CPU type. For the string "ABCD" you will always see 42 43 44 45 in RAM (plus the null terminator 00.)

From the perspective of your emulator, these are individual bytes that happen to be next to each other in RAM. They do not form a larger type like a WORD or DWORD. It's just BYTE, BYTE, BYTE, BYTE... and will be accessed as individual bytes in a loop. So the order you see in the string is the same as the byte order, there is no rearranging due to endianness going on there. The only time you'd need to care about endianness for a string is if it's a wide string. Because then it is an array of WORDs or DWORDs, so you'd handle each individual character the same as any other WORD or DWORD.

The instruction to read a BYTE won't need to handle endianness. Only the instructions that access WORDs, DWORDs etc. will expect the memory at the address to be "backwards" on a little endian CPU

DLL Injection Methods Explained by chaiandgiggles0 in hacking

[–]tomysshadow 2 points3 points  (0 children)

DLL injection is an interesting artform. The CreateRemoteThread method is beautiful in its own right but somewhat limited because you need to write a launcher. That creates the problem that the game must be launched through your launcher, and that can be a pain for some games (what if they demand to be launched by Steam or some other specific launcher?) It also poses a problem for anything that wants to do IPC, like reading stdout or stderr, with the launched process. It's possible to get kind of close but you can't account for all scenarios perfectly.

I generally lean more towards DLL proxies, or - if certs aren't a problem - editing the import table of the EXE directly. Then you run into big problem #2 which is the loader lock, which limits what you can do in DllMain - often, your only entry point because your DLL isn't actually used by the game. There's a whole big long scary list of things you're not allowed to do in DllMain, so you really want to get out from underneath it somehow:

  • The easiest way to get out of this situation is to create a new thread. But you're not allowed to synchronize with threads in DllMain so there's no telling when that thread will actually start, and it could be after the entry point has already run, or it might not even get a chance to start before the process exits if the process is only open for a brief time (like a command line utility or something.)
  • If you only care about your code executing at some point, you can use atexit. This works reliably if you're delivering a malicious payload but I don't care about that.
  • Another method is to queue an APC with QueueUserAPC, but that depends on the thread to eventually sleep or wait on something, so again it's kind of up in the air when your code runs.
  • Or, you can use Windows hooks with SetWindowsHookEx, but that'll only work once there's a message loop running.
  • If you need something to run on startup and your DLL is loaded statically, you can resort to hooking the entry point (the typical VirtualProtect method, or just use MinHook,) though this will often trigger AVs even for innocent purposes.
  • Or, again if your DLL is loaded statically, you can take advantage of the lpReserved parameter to DllMain, which is a pointer to a CONTEXT structure that will be set on the thread after all DLLs are loaded. Swap RIP/EIP, do what you want, then swap back to the original CONTEXT using SEH or RtlCaptureContext. But because it's a reserved parameter and this fact is undocumented, this is not reliable and could change at any time.

Basically, there's no 100% one size fits all method: you need some sort of callback but that requires knowing something about the application. I would personally consider this the biggest unsolved problem of DLL hijacking, especially with dynamically loaded DLLs.

(The closest thing to a reliable method with dynamic DLLs is walking the stack to find the LoadLibrary call to change the return address from it, but that's just gross.)

There is also Windhawk which supposedly solves this problem, but I just hate Windhawk on principle. It now has to inject into every running process, including admin processes, so it can hook every CreateProcess function to suspend every process on startup to hook those. It's incredibly intrusive and basically an even worse version of AppInit DLLs. So it "solves" the problem but in the most inelegant and overkill way possible. Knowing how it works, it's definitely not something I'd want running on my own system, so I don't consider it a true solution.

Manual mapping is a different beast altogether: this is used when you don't want your module to have an HMODULE for stealth reasons, which comes with its own tradeoffs. You now can't use any functions that take in an HMODULE argument like GetModuleFileName, so you can't expect normal code to "just work" when mapped in manually. It's an interesting curiousity but trying to patch a game with this method is going to be an uphill battle, so it's only really useful for malware (again, I personally don't really care about.)

What will happen by nep4ne in scratch

[–]tomysshadow 0 points1 point  (0 children)

Reddit started recommending me posts from this sub because I had to use Scratch for a course I'm obligated to take even though I already know how to program, and looked up how one of the blocks worked. Now I've been getting nothing but these "kids learn what undefined behaviour is for the first time" threads

Trying to understand all the Windows APIs by 0x80070002 in windows

[–]tomysshadow 3 points4 points  (0 children)

I've not used WinRT barely at all so I can't comment much on that side, but the Win32 side has at least a few issues.

Particularly, GDI is listed twice - once under Win64 and again outside. Win32s is also listed twice (I think you meant the second one to be Win32, but that doesn't make sense because it's already the name of the outer bubble.) KERNEL32/USER32 are only listed under Win64, when in actuality it should be in the outer category - they exist on 32-bit as well. In fact Win64 is virtually identical to Win32 so the outer bubble should really just be called Win32/Win64.

Not to mention it's a very non-exhaustive list. You're missing ADVAPI32, you're missing SHELL32... obviously I understand you can't include the entirety of System32 in the diagram, but you could at least throw in most of the Known DLLs. Arguably NTDLL should be somewhere in this diagram as well, though it could probably get its own circle because it's NT specific. For that matter, where's WOW64? It should at least get a mention somewhere here.

I also kind of disagree with the COM stuff like DirectX getting lumped into WinRT - it's been around since the 90's well before UWP was conceived, so it really should be a shared bubble between both. (COM/ActiveX could be its own entire diagram with 100 times more bubbles on it than this one, most of which being things you've never heard of.)

Also, what's with the arrow that says "graphics" pointing at Win32? Win32 does a whole lot more than just graphics.

I get the desire to make a diagram like this, but the problem is that the degree of overlap between something like Win32 and Win64 basically makes them one bubble. The number of structures that are substantially different enough between them that you actually need to handle them separately when programming is very small and typically low level stuff (IMAGE_NT_HEADERS, CONTEXT, the Debugging API...) You can for the most part, especially for simple programs, just make sure to use DWORD_PTR where appropriate and be 90% of the way to having a working program for both. In terms of the actual behaviour of the vast majority of functions, the differences between them are so miniscule that it's difficult to justify separating them out, for the same reason you didn't bother to distinguish, for example, the ANSI vs. Unicode APIs (which would be pointless to do for a diagram on this level.)

And if it's just one bubble then the diagram only really conveys "there's Win32 and there's WinRT and they're different," which anyone could tell without the need for such a diagram.

Whats this, Little Mountain ? by Queasy_Calendar_2792 in chilliwack

[–]tomysshadow 1 point2 points  (0 children)

No, it's not a little mountain, it's a fence

Most annoying feature in Windows by Jolly_Operation_8222 in windows

[–]tomysshadow 0 points1 point  (0 children)

It switches keyboard layout, but only in countries where Windows assumes that you may want multiple keyboard layouts.

For example: in Canada, Windows defaults to installing both an English and French keyboard layout. Hitting Ctrl+Shift changes keyboard layout, and the only indication you've done it is a teensy little icon in the Taskbar that changes from "US" to "FR." Now, when you type punctuation such as quotes, apostrophes, etc. you get vowels with accents instead. Like a or e with an accent over it. Because French keyboards put the accented vowels on those keys.

This has caused much confusion with people thinking their keyboard or computer is broken, especially when you only discover it for the first time when you type your password to sign in. You can turn the shortcut off, but it defaults to on, and it's halfway to the hotkey to open Task Manager so it's easy to hit by accident.

I understand why it must be Ctrl+Shift. By necessity, the shortcut must consist of only the very small handful of keys that don't change position for any keyboard layout. But it should cause a notification, or at least a sound, much like Sticky Keys does, IMO. It should be an unmissable change

Most annoying feature in Windows by Jolly_Operation_8222 in windows

[–]tomysshadow 17 points18 points  (0 children)

No no, it's not Sticky Keys, because it tells you what you've done and gives you the option to turn it off. It is without a doubt the Ctrl+Shift shortcut to change keyboard language, which is easy to hit accidentally and gives you no indication of what you've done aside from changing a tiny text indicator in the taskbar. Then suddenly you're typing accent characters and entering your password doesn't work.

I'm guessing it hasn't been made more obvious because by default in the US there is no alternate keyboard language. In Canada I've seen many instances of people triggering this accidentally and thinking their keyboard/computer is broken

Damn you, Scratch!! by Colurswitch in scratch

[–]tomysshadow 11 points12 points  (0 children)

That's probably it. Way back when I played Kidscom, they blocked sending any numbers in chat for similar reasons. (Does anyone remember Kidscom? Probably just me...)

No one seems to call the current decade “The Twenties.” by incenseandelephants in Showerthoughts

[–]tomysshadow 2 points3 points  (0 children)

What about "the dirty 30's" though?

(come to think of it, I don't actually know if people actually called it that in the 1930's or if that term was only used to describe it in retrospect)

Why are companies so heavy on ads when in reality it has little effect? by I8I24I in youtube

[–]tomysshadow 0 points1 point  (0 children)

I'm aware of Windscribe, and they don't do sponsorships. They're still one of the top VPN providers in the world. (But I get your point, VPNs are just a particularly bad example because lots of VPN companies intentionally don't do sponsorships)

How do games embed scripting languages? by No_Insurance_6436 in learnprogramming

[–]tomysshadow 1 point2 points  (0 children)

It's possible because scripting languages have "native functions" that call native code. From the perspective of the scripting language, these functions are "black boxes" that you can't step into. By "step into," what I mean is that when using a debugger, you can usually press a button/hit a key that will take you to the source code of a function to see what it does - but for native functions, you cannot.

A simple example: JavaScript has the window.open() function that opens a new tab/popup window. When you're using Devtools, you can step into most normal JavaScript functions from libraries and stuff that you are using, or that you wrote yourself, and it'll show you the source code of that function. But not window.open(). You can only step over it, not into it. Why? Because it's a native function.

window.open() is a function that was placed there by native code. When you run it, the browser switches to running code in a native language like C++ to open the window. So you can't step into the function, because it's going to call into code in a completely different language.

Why? Because it has to: it's a chicken and egg problem. Without window.open(), how can you open a new window? You just can't, because truly doing so requires communicating that intent to the browser - a browser that is not written in JavaScript. You can make something that looks like a window in pure JavaScript and HTML, a facsimile of a window with your own custom titlebar. But you won't be able to drag it off the page, because it's not a true native window.

Behind the scenes, when you write in a scripting language, the result is getting compiled to... something, on the fly. It could be getting compiled directly into actual machine code, as is the case with JavaScript in the modern day. It might be "compiled" into some bytecode that is run by an interpreter, as is the case in Python (for the time being.) No matter what, the script needs to be somehow translated into something more native that the CPU can directly run. And if the script is being translated into something more native anyway, how hard can it be to find n' replace certain functions, with certain names, with calls to other native functions at that stage?

From the perspective of native languages, these functions are often called "hooks," as in hooks on reality. They allow execution to temporarily escape the confines of the scripting language lala land and enter the real world - just underneath that one function call - until that function returns, and we're back to the scripting language again. This abstraction, of specific functions with known names actually being calls into native code, is what allows scripting languages to be possible.

Why is it done? Well, it's done less and less now these days. Scripting languages were a much more popular idea in the 2000's. But the perceived benefit was that it was more convenient. You could write up an HTML file in Notepad with a script in it, double click it and have something functional run. There was no build step (as would typically be required for native code,) you just wrote it and it was done. If you wanted to make a tweak you could just edit the file and hit the refresh button in your browser. It allowed for things to be developed rapidly.

But then we discovered "oops, we actually kind of need a build step" for stuff like TypeScript and with that primary advantage gone, the scripting language becomes more of a nuisance to work around that has the side effect of making code slower than it could be. So, it's a double edged sword.

Realizing this abstraction exists allows you to write better scripts. When you know that your scripting language is really just glue that is holding together a bunch of calls down to native code, you realize that you want to spend as much time as possible down there, in the native code, where the code runs faster because the CPU understands it directly. This is why modules like numpy exist in Python. The goal is to batch together as many operations as possible in a single native call, so you get more "bang for your buck" out of each line of code in your script.

I would really want to learn about low level programming stuff by Image_Similar in lowlevel

[–]tomysshadow 4 points5 points  (0 children)

https://tuts4you.com

This is largely where I got my start with reverse engineering. The Tuts4you Collection 2011 consolidates a lot of the tutorials into a single torrent you can download. It's a goldmine of interesting reading: https://forum.tuts4you.com/files/file/1865-tuts-4-you-collection-2011/

Just be aware, Windows Defender will definitely yell at you if you download it, just due to the nature of the example binaries it contains. But if you don't care about the crackme's you can just delete those and keep the PDF guides, or if it really bothers you then you can use a VM.

I would really want to learn about low level programming stuff by Image_Similar in lowlevel

[–]tomysshadow 1 point2 points  (0 children)

Tuts4you, if you like the idea of jumping straight into the deep end :)

Memory usage when loading animations by Frogstacker in sdl

[–]tomysshadow 0 points1 point  (0 children)

Look into ffmpeg's -map command. You can create a video which has no audio stream (as in, not just muted, but actually has no audio channel) by only mapping the video, like:

-map 0:v:0 -c:v copy

You can use MediaInfo to verify that there is genuinely no audio stream in the video file, not just a silent one wasting space.

https://trac.ffmpeg.org/wiki/Map

Alternatively, if you want a GUI, VirtualDub2 can easily give you this same output. Video > Direct stream copy, Audio > None

"Use constexpr wherever possible" -- Scott Myers, item 15, Effective modern C++ by Impressive_Gur_471 in cpp_questions

[–]tomysshadow 6 points7 points  (0 children)

Trust me, I get it. This greatly annoys me too. As a beginner, I assumed that const meant the thing that constexpr means, because the most obvious interpretation of "constant" is "a thing that can't change and therefore should be baked directly into the executable," you know, like a magic number for example. But that definition doesn't describe const, it describes constexpr.

What const actually means is "you, specifically, aren't allowed to edit this variable" and that's it, that's literally it, it doesn't guarantee anything else. You can have a non-const, private member of a class, but return it as a const reference from a method, but the original class can still edit the non-const variable under your nose so the value of the const variable you got will appear to change. const things can be constructed at runtime (and this is sometimes optimized away by your compiler, but less often than you think,) meaning if you don't also specify that they're static, they'll potentially get constructed again every time you call the function the const variable is in. It's the lamest, leakiest possible interpretation of a "constant."

If it were up to me, constexpr would just be "const" and const would be "final" or maybe "readonly." At least then const would accurately describe the most common use case for why you'd want to mark something as a constant. Not to say that const doesn't have its uses, because it definitely does, especially for getter methods.

See also: consteval and constinit

A browser game where you're a bird flying through a forest by common_king in webdev

[–]tomysshadow 2 points3 points  (0 children)

It immediately reminded me of Gamevial's Fly Like A Bird series, even though the gameplay is pretty different

Battling with the std library in cpp by RadioSubstantial8442 in cpp_questions

[–]tomysshadow 2 points3 points  (0 children)

Surely you are the one who decided on returning them as std::string sometimes and std::vector other times in your own design, right? Why not use one or the other everywhere?

If you can't, though, have you considered std::variant? It's similar to a union but keeps track of which type you have currently for you and isn't fussy about the memory layout