JMP unexpected behavior in Shellcode when next(skipped) instruction is a variable definition
TL;DR : The method you are using to convert your standalone shell code program shellExec
to a shell code exploit string is buggy.
Based on the information given, I suspect the problem is the way in which you are using disassembly output to generate the final byte stream that gets converted into your shell code string. Likely the disassembly output had confusing output and possibly duplicated values. While trying to disassemble data (mixed with the code) it tried to output the shortest encodeable instruction to finish consuming all the data and then discovered you had a JMP target and duplicated some of the bytes as it backed up to re-synchronize. Whatever process was used to convert the disassembly to binary didn't take this kind of issue into account.
Don't use disassembly output to generate the binary file. Generate your standalone executable with the shell code (I believe shellExec
is the file in your case) and use tools like OBJCOPY and HEXDUMP to generate the C shell code string:
objcopy -j.text -O binary execShell execShell.bin
hexdump -v -e '"\\""x" 1/1 "%02x" ""' execShell.bin
The objcopy
command takes the execShell
executable and extracts just the .text
section (using the -j.text
option) and outputs as binary data to the file execShell.bin
. The hexdump
command just reformats the binary file and outputs it in a form that can be used in a C string. This process doesn't involve parsing any confusing disassembly output so doesn't suffer the problem you encountered. The output of hexdump
should look like:
\x48\x31\xc0\x48\x89\xc6\x48\x89\xf7\x48\x89\xfa\x49\x89\xd0\x4c\x89\xc1\x48\x89\xcb\xeb\x07\x2f\x62\x69\x6e\x2f\x73\x68\x48\x31\xc0\x48\x8d\x3d\xef\xff\xff\xff\x88\x47\x07\x48\x89\x7f\x08\x48\x89\x47\x10\x48\x8d\x77\x08\x48\x8d\x57\x10\xb0\x3b\x0f\x05
This differs slightly from yours which was:
\x48\x31\xc0\x48\x89\xc6\x48\x89\xf7\x48\x89\xfa\x49\x89\xd0\x4c\x89\xc1\x48\x89\xcb\xeb\x07\x2f\x62\x69\x6e\x2f\x73\x68\x48\x31\x48\x31\xc0\x48\x8d\x3d\xef\xff\xff\xff\x88\x47\x07\x48\x89\x7f\x08\x48\x89\x47\x10\x48\x8d\x77\x08\x48\x8d\x57\x10\xb0\x3b\x0f\x05
I've highlighted the difference. After the string of bytes /bin/sh
your output introduced an extra \x48\x31
. The extra 2 bytes in your shell code string are responsible for the code not running as expected in the target executable.
Callback in C++ to a class member
The basic idea is, you define an abstract Callback class, which actually gets passed to your interface. This one calls back to a function passing a single int parameter:
struct Callback {
virtual ~Callback(){}
virtual void operator()(int param)=0;
};
This class allows YOUR implementation to be free from knowledge of the code you need to call back into. Of course, to call into a class, you do need an instantiation of Callback that DOES have knowledge of its target. So you then also provide a templated child class that makes it easy for users of your Library to to bind a method in one of their classes to an instance of the generic Callback :-
template<class T>
class ClassCallback : public Callback {
T* _classPtr;
typedef void(T::*fncb)(int param);
fncb _cbProc;
public:
ClassCallback(T* classPtr,fncb cbProc):_classPtr(classPtr),_cbProc(cbProc){}
virtual void operator()(int param){
(_classPtr->*_cbProc)(param);
}
};
To create an instance of the callback from their class, code would look like this. And the invocation is simple too:
struct CMyClass {
Library* _theLibrary;
CMyClass(Library* init):_theLibrary(init){
Callback* pCB = new ClassCallback<CMyClass>(&myClass,&CMyClass::OnCb);
_theLibrary->SetCallback(pCB);
}
void OnCb(int){
// callback triggered
}
void Run(){
_theLibrary->DoWork();
}
};
In Summary: Library.h then would look like this. Define the abstract callback class, your library class, and the templated utility class that the customer uses to wrap their their class and its callback method with:
// This is the header file what our customer gets
struct Callback {... };
class Library {
Callback* _pcb;
public:
void SetCallback(Callback* pcb){_pcb=pcb;}
void DoWork(){
int status=0;
(*pcb)(status);
}
~Library(){delete _pcb;}
};
template<class T> struct ClassCallback{ ... };
Is there an instruction to pack a register in amd64 assembly?
pshufb
is probably the instruction you want.
It takes two MMX / XMM registers as arguments. The first one is the data to shuffle; the second one (the "control mask") controls how it is shuffled.
The data in each register is broken down into bytes. For each byte of the output, the processor uses the corresponding byte in the control mask to decide how to set it:
- If the high bit (
0x80
) of the mask byte is set, the result for this byte is zero. - Otherwise, the lower half of the mask byte is used as an index into the input bytes. For instance, if the mask byte is
0x03
, the third byte of the input is used for this byte of the output.
By way of example, a control mask of 0x0f0e0d0c0b0a09080706050403020100
will reverse the bytes in a register.
Note that if you're just working with normal integer registers, getting the data in and out of the appropriate registers may be awkward. Using compiler intrinsics may make this easier.
Related Topics
Find Installation Path in Linux
Autostart Javafx Application on Raspberrypi
Quickest Way to Select/Copy Lines Containing String from Huge Txt.Gz File
How Is Numa Represented in Virtual Memory
Is It Necessary to Flush Write Combine Memory Explicitly by Programmer
Dynamically Pick The User Gui and UId Who's Running Docker at The Host from Entrypoint
PHPmyadmin, Neginx Error.Log - Check Group Www-Data Has Read Access and Open_Basedir
Mount -T Cifs Works on One Version of Linux But Not Another
In Gitlab Ci The Gitlab Runner Choose Wrong Executor
Making Pairs of Words Based on One Column
Ftrace: Only Print Output of Trace_Printk()
Amazon Ses on Google Cloud Computing Instance Vm Using Postfix
How to Modify The Linux Kernel to Change The Version String That Uname Returns
Open Website from Within Eclipse's Internal Browser
Process-Local Override of Name Resolution
Where Do Char Device Appear After Cdev_Add() Registers Successfully with Major on 117.
Aws Ec2: How to Remount Previous Ebs Volume Using Pivot_Root
Accessing Apache2 Residing Inside Docker Container from Host Machine Web Browser