[HN Gopher] Tony Hawk's Pro Strcpy
___________________________________________________________________
Tony Hawk's Pro Strcpy
Author : ndiddy
Score : 329 points
Date : 2024-08-07 16:48 UTC (6 hours ago)
(HTM) web link (icode4.coffee)
(TXT) w3m dump (icode4.coffee)
| jonhohle wrote:
| This is awesome!
|
| I've been doing some PSX decompiling and there are lots of
| similar things there as well. Interestingly, something like
| `memmove` is linked in using an SDK library[0], but `strcpy` is a
| function provided by the BIOS. Later version of the SDK could
| patch that out for a library version, but as late as 1997 it
| hadn't been.
|
| 0 - https://github.com/Xeeynamo/sotn-
| decomp/blob/master/src/main...
| anthk wrote:
| I'd love a reimplemeantion in C+SDL2 (and OpenGL 2.1) of the
| former console games.
|
| Now there are the N64 games being ported to PC with
| decompilers, I can only hope. Inb4 "there are native PC
| versions of these, you know"... most recompiled N64 games with
| the FX's being 'deshaderized' to pure textures (or simpler
| FX's) can be run in toasters such as cheap netbooks from 2009
| and nearly anywhere.
|
| They even ported Super Mario 64 to the 3DFX API. I know, the
| most complex games accesing the N64 framebuffer with complex FX
| will require OpenGL 3.3 to mimic that microcode; but, as I said
| before, when the engines run uber-fast on anything post Pentium
| III, is not something difficult to 'mimic' these in software
| while the rest it's running GL 2.1 accelerated.
| bitwize wrote:
| > They even ported Super Mario 64 to the 3DFX API.
|
| That's... not surprising. UltraHLE ran SM64 like a dream, and
| the HLE bit referred to the fact that the emulator translated
| 3D calls to the Glide API rather than attempting to emulate
| the 3D hardware directly.
| anthk wrote:
| Yeah, I knew about that, so this it's just transcribing
| instead of translating. But I'd guess SGI machines (IRIX)
| being OpenGL bound (they invented it) the N64 would map the
| microcode to GL funcs much better.
| bitwize wrote:
| Glide was modelled after OpenGL, so I'm guessing the
| mapping was not that much of a stretch anyway.
| perihelions wrote:
| - _" If I was lucky it would be strcpy (opposed to something like
| strncpy)"_
|
| it really ought to have been strncpy, I'm sure Tony Hawk who's
| lauded for his advocacy of safety gear would prefer to be
| associated with safer string copying
| kragen wrote:
| strncpy is definitely not safer; it produces unterminated
| strings when it hits _n_
|
| basically you should almost never use strncpy; it's
| specifically for fixed-size fields like this:
| struct dirent { unsigned short inode; char name[14]; };
|
| and in those cases more often than not the pad byte should be a
| space rather than a nul
|
| strncpy should never have been added to the standard library
| sidewndr46 wrote:
| What is the preferred solution here? I usually just use
| "memset" to zeroize the whole destination string, then tell
| "strncpy" that my destination is 1 byte shorter than what it
| really is.
|
| The real issue I've ran into is that "strncpy" assumes the
| source is null-terminated.
| connicpu wrote:
| C11 adds `strcpy_s` which takes (dest, destsz, src) and
| returns an errno_t which will report an error if the src
| string is longer than destsz, as silent truncation is often
| not a desirable behavior. It also assigns dest[0]='\0' on
| error so you don't get an unterminated garbage string.
| david2ndaccount wrote:
| Only msvc provides strcpy_s and they don't conform to the
| standard. Other libcs don't provide it. Ignore everything
| from Annex K and write your own wrappers around memcpy.
| You should always know the size of your buffers.
| connicpu wrote:
| Ah that sucks. Guess C is just stuck like this for the
| long term. Writing your own functions is still the best
| advice :'(
| david2ndaccount wrote:
| Use memcpy and do the size check yourself beforehand
| (taking the appropriate action if it doesn't fit). Avoid
| any function starting with str except for strlen. Prefer
| pointer+length instead of relying on nul-terminated
| strings.
| paulryanrogers wrote:
| strlcpy?
| saagarjha wrote:
| memccpy, then use the return value to terminate.
| pjmlp wrote:
| Use a proper C string library like SDS.
|
| Or move up from the 1970's Bell Labs, adopt C++ with the
| respective compiler switches to have bounds checking
| enabled for _operator[]()_.
|
| Better yet, use something else instead of one of those two,
| pick whatver is your fancy.
| Sesse__ wrote:
| The sanest solution is, surprisingly, snprintf(dst,
| sizeof(dst), "%s", src).
| david2ndaccount wrote:
| The correct thing to do is to use memcpy and to know the size
| of both the destination buffer and the source buffer. If the
| source buffer won't fit, then you need to take an application-
| specific action (is truncation ok? do you have to abort the
| whole operation? Do you re-alloc the destination buffer? etc.)
| strncpy almost always does the wrong thing.
| thekevan wrote:
| I read that he used to drive around and when he saw a
| skateboarder, he'd yell "do an ollie" and then give them a new
| helmet.
| nj5rq wrote:
| Very good article.
| makin wrote:
| A bit of a shame about the exploit applying to THUG PRO. The mod
| is played to this day, since the more competitive side of the
| Tony Hawk franchise has been dead for almost twenty years (with
| the exception of the THPS1+2 remake, which was but a blip in the
| scene).
|
| The mod itself is over 10 years old now, and I think the original
| developers are gone, explaining why no one was interested in
| fixing it when Ryan reported it. But this means that now the mod
| is unusable, no one is going to want to risk a full privilege
| exploit taking over their PC.
|
| Hopefully this article reaches someone who's a bit more
| interested in patching the mod.
| rlabrecque wrote:
| I wish I had the time, because it would be fun. Back when I DID
| have time, I actually got that thug1 source code almost
| playable on Windows. That source code was only for the console
| versions, and the code assumed if it was compiling for windows
| (and not Xbox windows..) it was only for tools, so a lot of
| pieces worked completely differently.
| auto wrote:
| I've read so many flavors of this sort of exploit analysis over
| the years, and if I get to read 100 more I'll be all the happier
| for it.
|
| Great article!
| Retr0id wrote:
| > The more interesting thing about the habibi key is that the
| public key modulus only has a 4 byte difference compared to the
| Microsoft RSA public key. For reference the MS key is a 2048 bit
| RSA key. I've asked a few people how this might be possible and
| the answer I got is "if you change the exponent to something
| small like 3 you easily factor out a similar key". This should
| require that the exponent of the public key is also patched to
| "3". However, none of the shell code payloads that use the habibi
| key ever change the exponent used by the RSA signature
| verification routine. Presumably it's still performing the
| validation using the exponent 65537 so I'm not entirely sure how
| this works. Perhaps someone more knowledgeable could shed some
| light on it.
|
| A random 2048-bit integer has a moderate chance of being
| trivially factorizeable (I don't know the precise odds but we can
| infer that it's roughly on the order of 2^-32 (for some
| definition of trivial) without doing any real math). Presumably,
| they wrote code that did something like this:
| while true: randomly tweak/increment 4 bytes of the
| public modulus spend 1 millisecond trying to factor
| it did it work? if yes, we're done here.
| else, try again.
|
| The resulting public modulus likely has lots of smaller factors
| (it should be possible to verify this, if anyone knows where I
| can find the "habibi public key"?). Although an RSA modulus
| normally has exactly 2 prime factors, the math still works out if
| you have more (as long as e is coprime).
| fxtentacle wrote:
| Let me try to explain that. You start with a random 2048-bit
| integer. You then change the lower bytes to make it divisible
| by 3. This is easy because you're only working on the public
| key. Now that the public key is divisible by 3, you use
| Fermat's little theorem which tells you that the private key
| must be divisible by 3 and have a sum of digits that is
| divisible by 3. This lets you skip most possible private keys,
| thereby reducing the compute needed to factorize it by a few
| orders of magnitude. And maybe you get lucky and they use that
| RSA implementation which uses exactly 2 prime factors, because
| then you already know that one of them is 3 and you just divide
| the public key by 3 to get the other prime factor.
|
| EDIT: Wikipedia says "The structure of the RSA public key
| requires that N be a large semiprime (i.e., a product of two
| large prime numbers), that 2 < e < N, that e be coprime to
| ph(N), and that 0 <= C < N." and later "the same algorithm
| allows anyone who factors N to obtain the private key."
|
| which in the contest of the Xbox hack means that if you force N
| to be divisible by the prime 3, then the other prime which is
| used for generating the private key has to be N/3 => You have
| successfully factored it.
|
| EDIT2: Here's code for signing with the Habibi key:
| https://github.com/XboxDev/xbedump/blob/b8cd5cd0f8b1cbc4e64f...
|
| As you can see, it'll replace the last 4 bytes with 0x89, 0x9c,
| 0x90, 0x6b and then start by dividing it by 3 and using that to
| generate a suitable private key.
| Retr0id wrote:
| Ah, thanks for finding that code.
|
| Here's the original public modulus as an integer: http://fact
| ordb.com/index.php?query=207401193272587237602760... (which
| can't be factored, at least not any time soon)
|
| And here's the patched version: http://factordb.com/index.php
| ?query=173718524353649322341982...
|
| And exactly as you say, it's divisible by 3, leaving behind a
| single large prime (so I was wrong about there being more
| factors)
| brcmthrowaway wrote:
| This gives me an opportunity to clarify a myth from my childhood.
| Was Tony Hawk the first ever to hit a 720?
| zimpenfish wrote:
| https://en.wikipedia.org/wiki/Aerial_(skateboarding) says "The
| 720, two full mid-air rotations, is one of the rarest tricks in
| skateboarding. It was first done by Tony Hawk in 1985, and it
| wasn't something he planned to do."
|
| (Which is presumably "the first recorded" but I'm guessing if
| someone had done it, they'd have been shouting about it and
| -probably- the only kind of person who could pull it off would
| be a pro skater anyway?)
| detoured299 wrote:
| At that time only a few pro vert skaters would have had the
| ability to throw 720s, yeah. Nowadays a good number of ams
| can too.
|
| The rarity of seeing a 720 or above has as much to do with
| the fact that most skaters don't skate vert - instead skating
| street or smaller transition - as the trick's difficulty.
| Outsiders tend to imagine large spins are the holy grail of
| skate moves but almost all skaters aren't interested in them
| for aesthetic reasons among others.
| voytec wrote:
| He worked much longer for the 900 but more importantly - he
| repeated the 900 at the age of 48[0]!
|
| [0] https://youtu.be/TnvPt_a7iOQ?t=93
| ComputerGuru wrote:
| FYI, what looks like a section header icon followed by the text
| "So what's the habibi key?" is actually a clickable expanding
| segment (html details). You should click it if you're interested!
|
| A question I have is where/when/how the corresponding _private_
| habibi key was released /leaked, if the story about it being used
| exclusively by the linux console group to prevent pirated content
| from being used is true. OP clearly was able to patch the four
| byte difference between the MS key and the habibi key to then run
| "unsigned" (but, actually, signed with the habibi private key)
| executables, so they clearly got their hands on it.
| jdlyga wrote:
| Imagine a VSCode plugin that made up trick names and gave you a
| combo points score at the bottom for your continuous keystrokes.
| Tony Hawk's Pro-grammer
| i_read_news wrote:
| I think this would be more fun for VIM keybindings, where there
| is a higher skill level (to get cooler combos of course).
| Rebelgecko wrote:
| Thanks for sharing, the other articles on this blog are equally
| fascinating
| Jerrrrrrry wrote:
| It may not be possible for me to articulate how fucking insane of
| an accomplishment this is.
|
| Xbox 360...._softmod_.... via the park name on a Tony Hawk game.
|
| 24 segment ROP chain :')
|
| His rightful lamentation for the hypervisor, concise functional
| write up, and immediate thoughts of an x360 botnet make this the
| greatest xbox 360 nostalgia gut-punch of all time.
|
| kudos++
| Reason077 wrote:
| In Tony Hawk's defence, he's a pro skater, not a security
| analyst. Limited time behind the keyboard in the late 90s/early
| 2000s grinding on his soon-to-be iconic game series would have
| been spent making sure 900 McTwists felt really natural, not
| auditing code for buffer overruns!
| JoshTriplett wrote:
| This seems like a great example of having the wrong security
| mindset in console development. "We're the only thing that can
| write this saved data, so we only have to parse what we wrote" is
| a very common console mindset, and fundamentally wrong when
| people can prepare artificially constructed saved data.
|
| (Completely separate from that, consoles shouldn't be treating
| users as the adversary, but given that they _do_ , games are
| failing to have a security mindset consistent with that stance.)
___________________________________________________________________
(page generated 2024-08-07 23:00 UTC)