[pwnable.kr]_Memcpy Problem solving

Right then, haha. Every problem I pick,
the difficulty just goes utterly mental,
doesn’t it?
It’s been quite lunatic so far, ōxō.It’s been quite lunatic so far, ōxō.

|참고 사항|

Screenshot.1
Alright, then. If
I just do a rough-and-ready literal translation of the passage,
it goes something like this:
Are you tired of hacking?, take some rest here.
(으따 해킹하는 거 지겨워졌고 마이 잠깐 좀 쉬랑께?)
Just help me out with my small
experiment regarding memcpy performance.
(memcpy 성능 실험 좀 도와달랑께)
after that, flag is yours.
(그럼 키값은 니꺼랑꼐?)
Right then. Apparently,
it’s not a hack this time around.
Still, best to have a look, wouldn’t you say?

Right then. As before, just fire up your terminal, get yourself connected,
and then, naturally, you’ll employ the trusty
command to have a gander at the files.
Is ls
Right. So,it’s just memcpy
and readme
,is it?
That’s your lot.
Doubt we’ll be snagging any keys from this account,then.

Right, then. Looks like we’ll
probably need a temporary bit of privilege escalation,
likely via an nc
listener, to get our hands on that key.

Screenshot.4
Right then. Let’s just hop onto that listener.
And as soon as we’re in,
you’ll see memcpy
is running.
Turns out, this file…
It appears to be operating as a C function,
then, designed for copying memory.

The memcpy
file apparently takes
numbers within a given range.
Feed it anything outside that,
and it just bails immediately.
But get ten in-range numbers into it,
and then it’s said to perform both a
slow and a fast memory copy process.
Right. It only gets through five stages of that process,
and then suddenly…
Then it just spat out an error and promptly died. ōxōThen it just spat out an error and promptly died. ōxō
Right. So, what we’ve found is this program has a tendency to
just cut out mid-process.
And,as the messages on execution rather plainly suggest
it’s all tied to the slow and fast memcpy
implementations.
Right. Apparently,
if you can compare
the various data sizes without it cutting out mid-process,
and manage to get through all the sections,
it’s said to hand over the key.
So,I suppose we’d better dive into the source code, then.
1 | // compiled with : gcc -o memcpy memcpy.c -m32 -lm |
Right. So, back in experiment5
,
the fast_memcpy
section threw an error, didn’t it?
That just cut off the rest of it.
Means we can only actually get the key if all
the subsequent sections run through without a hitch.
1 | // run experiment |
1. It runs ten times, as per the input count.
2. Memory is dynamically allocated to the set size,
and that’s stored in dest
.
3. The rdtsc()
function, for precise timing, calculates
the duration of the slow memory copy and puts that into t1
.
4. And t2
, of course, will then hold the time taken for the fast memory copy.
5. Right. So, the slow memory copy, that’s done byte by byte.
The fast one? That’s block by block.
→ Solution : First off, we’ll need those functions where
the slow and fast memory copies are actually defined.
Right. You’ll need to head over to that section and
figure out what the function’s actually doing.
Next slow\_memcpy, fast\_memcpy
It’s a function.
1 | char* slow_memcpy(char* dest, const char* src, size_t len){ |
Right. slow\_memcpy
,
that’s your basic byte-by-byte operation
from source to destination.
Simple enough, but a bit sluggish,
mind you. fast\_memcpy()
, on the other
hand, well, that’s designed for 64-byte chunks…
Right then. If it’s anything under that,
it just runs slow\_memcpy
.
But for 64 bytes or more,
it then executes the assembly-level code
Right then. In the fast\_memcpy()
section,
it cut out midway through execution, didn’t it?
That meant this assembly code simply wasn’t able to
properly get invoked, thus throwing an error.
Right. The analysis breaks down as follows.
1 | __asm__ __volatile__ ( |
movdqa : Right.The’Aligned Double Quadword Move’.
Right. It takes the double quadword from the source operand
—that’s your second—and moves it to
the destination operand, which is the first one.
Right then.
This instruction moves a double quadword between an XMM
register and a 128-bit memory location,
or between two of those…
…XMM registers. And, naturally,
it can be used for movement between those.
Now, regarding the source or destination operand…
Right. If your operand’s memory-based,
it absolutely has to be aligned to a 16-byte boundary.
Fail to do that, and you’ll get yourself a
General Protection Exception (#GP).
movntps : Right then.
That’s for storing packed single-precision floating-point values,
utilising that non-temporal hint, of course.
then. You’re using the non-temporal hint to move
the packed floating-point values from the source operand,
over to the destination.
…operand, and that, naturally,
prevents any data caching whilst it’s being written to memory.
Right then. In movdqa
the’mov’bit there is,of course,
your instruction for shifting values about.
And’dq’? Well,that’s just your’double quad’, isn’t it?
Right then.
That instruction, it’ll throw an exception if it’s not aligned to
a 16-byte boundary.So, if you just ensure
the destination operand’s address is 16-byte aligned,
that’ll sort the issue right out.
Right then. We’ll just fire up GDB,debug it,
and then go about snagging that key, won’t we?
ㅋㅅㅋ

Screenshot. 6
1 | cd /tmp |
Right then. Once we’ve executed that through GDB,
we’ll then step into the fast\_memcpy
function and have a proper look, shall we?

Screenshot. 7
Right then. It’s sat at that location,
and the EDX value is 0x080487cc
.
Up to the fourth instance,
the alignment was perfectly fine,
so no errors popped up.
But the fifth one? It wasn’t aligned at all.





Right then. Just set a breakpoint at
the fast\_memcpy
function,
specifically at +71. Check the register value,
and you’ll find EDX is indeed aligned at 804d060
Essentially,
it’s 8 bytes short of 64,
meaning you’ll need an 8-byte offset.
And for any other values you’re debugging,
it’s fair to assume they’ll
all be missing 8 as well.
So, we’ll just add eight to the fifth value and
every subsequent one after that…
8 16 32 64 128 256 512 1024 2048 4096
8 16 32 72 136 264 520 1032 2056 4096
then.
So, it’ll assume that form we’ve just established.
And armed with that little theory of ours,
we’ll then just fire up an nc
listening server…
…feed each of those in, and then you’ll finally manage to snag the key.
Right. One could,naturally,dabble with other approaches,
I suppose.But for my money,using GDB is probably
the most sensible way to go about it.
So, if you run the program,
you’ll find the key value displayed, much as below.

Screenshot. 9
With the key value we’ve just, ah,’snagged’,
you simply head back to the start,pop it into
the blank,and then,naturally,hit that’auth’ button.

Screenshot.10
Right.
And then you’re presented
with a message about securing 10 points


Screenshot.11
then. And upon returning,
you’ll find it’s indicated
with a green dotted line.
Signifying it’s, well, resolved.
And thanks for actually
bothering to read through all that.
Right then.That’s done, then. :)

Right then.
Hope your day isn’t completely rubbish,
and whatever you’re cracking on with goes smoothly.
It’s a bit of a scorcher today,mind you,
so try not to go getting heatstroke.
And, naturally,
do be careful of that Wuhan pneumonia.
