ASM = Assembly.
Every single machine runs on a processor, and every processor has an assembly archiecture. Xbox 360's Assembly Archiecture is PowerPC, so ALL files that are ran, or just loaded into memory can ONLY be disassembled with PowerPC. So, lets for example take what Bitwise released.
[code=cpp]
*(long long*)(0x822EA24
= 0x8921005060000000;
[/code]
[spoiler=Something quick]
I'm going to make this noob proof. Basically, in hexadecimal (012345679ABCDEF) 2 digits is 1 byte. (e.g. 01, 05, 15).
Data type Data Format Size (Bytes)
char byte 1
bool byte 1
short word 2
int double word 4
long double word 4
float single precision 4
double double precision 8
long long quadruple word 8
Note also, a pointer (*) is aligned by 4 bytes (So, if you was to do sizeof(bool*) it would return 4). Also note, multiply the byte sie by 8, to get the bit size (e.g. 4*8 = 32)
Now, take the value we set to that address, and seperate the bytes (So it's easier to count how many are there)
89 21 00 50 60 00 00 00
1 2 3 4 5 6 7 8
As you can see, there are 8 bytes. The value is also an interger (intergers are fixed numbers (e.g. can not be set to 1.3)) so the only logical data type to cast with, is long long.
So now you understand data types why when/why to use them. Lets see why that value.
Every assembly language has an instruction set. They are compiled from opcode. In PowerPC, all instruction's are 32bit, so the opcode is going to be 32bit.
OPCode works strange at first, but you get used to it. If an instruction has no operands, the whole 32bit value is registered as opcode. NOOP for example, stands for no operation, which means to do nothing. In all ASM archiectures, the NOOP instruction is just;
nop
In PowerPC, the opcode for NOOP is 0x60000000.
OPCode works differently depending on how the instruction works, and the data used.
Instruction's such as li (Load Immediate (immediate is a 16bit integer)), lwz (Load Word with Zero (In PowerPC, a Word is 32bits not 16bits)) stw (Store Word) and so forth regarding data formats, work in a very simple manner.
As I said, all instructions are 32bits, which is only 4 bytes.
0-8 = OPCODE
8-16 = 1st OPERAND
16-32 = 2nd OPERAND
For example, li r3, 0 is;
38 60 00 00
And li r4, 1 is;
38 80 00 01
See how the second byte increased by 0x20? Each increment within the register number, will increase the value by 0x20.
r0 = 0x00
r1 = 0x20
r2 = 0x40
r3 = 0x60
r4 = 0x80
r5 = 0xA0
r6 = 0xC0
r7 = 0xE0
When we get to R8, the OPCode gets increased by 1 (The first byte), and the 2nd byte resets.
So li r8, 0 is
39 00 00 00
r8 = 0x00
r9 = 0x20
r10 = 0x40
r11 = 0x60
r12 = 0x80
r13 = 0xA0
r14 = 0xC0
r15 = 0xE0
Nothing higher can be used. The opcode can only range from 0x38 to 0x39. 0x40 is getting into branching.
Now, here is what a load instruction looks like (The memory instruction, does not include li, lis ect)
lbz <myDestionation>, <myOffset>(<myPointer>
lbz = Load Byte with Zero.
myOffset is an immediate, which as I said before is a short. In C++ this is;
[code=cpp]
unsigned char myDestionation = *(unsigned char*)(myPointer + myOffset);
[/code]
lbz's opcode starts at 0x88, and ends at 0x89. Regarding the second byte, r0 is now the pointing register number (e.g. r1 used, r0 = 0x01) I'm going to use X in the list, as a place holder.
r0 = 0x0X
r1 = 0x2X
r2 = 0x4X
r3 = 0x6X
r4 = 0x8X
r5 = 0xAX
r6 = 0xCX
r7 = 0xEX
INCREASE (OPCODE is now 0x89)
r8 = 0x0X
r9 = 0x2X
r10 = 0x2X
r11 = 0x6X
r12 = 0x8X
r13 = 0xAX
r14 = 0xCX
r15 = 0xEX
Now, remember the value we were using.
89 21 00 50 60 00 00 00
1 2 3 4 5 6 7 8
0x89210050...
0x89 = lbz 2nd register set opcode
0x21 = r1 OR r9 (depending on the set of registers used (r0-r7 or r8-r15)
0x0050 = offset
So as an instruction, this will look like
lbz r9, 0x50(r1)
If you have forgot how we add that up, re-read it.
as I said before, NOOP is 0x60000000
SO
0x8921005060000000
is....
lbz r9, 0x50(r1)
nop
[/spoiler]
How that you have read the logic behind Bitwise's bypass, I will now tell you how it works.
Located at 0x822EA248, is the instruction;
lbz r10, 0x50(r1)
I'm not going to go into detail since r1 is the stack pointer, and it means I will have to explain stack. All you need to know, is located at 0x50 in the stack frame inside this function, is a local variable. The reason he use's long long, is since it is 8 bytes. So since instructions are 4 bytes, writing with a value of 8 bytes and a 8 byte data type, will overwrite into the next instruction. So, doing
[code=cpp]
*(long long*)(0x822EA24
= 0x8921005060000000;
[/code]
is the same as doing
[code=cpp]
*(int*)(0x822EA24
= 0x89210050;
*(int*)(0x822EA24C) = 0x60000000;
[/code]
Originally, it would be
lbz r10, 0x50(r1)
ori r9, r10, 0x10
stb r9, 0x50(r1)
And he is altering it, to
lbz r9, 0x50(r1)
nop
stb r9, 0x50(r1)
Which as you see, this will not preform the ORI instruction (Which OR's 0x10 to the local variable). This is done when xbdm.xex is found active in memory (So in noob terms, if you have xbdm.xex as a plugin in dashlaunch it will be detected)
So this will stop the system from detecting you're on a modified console (Since only modified console's can load third party title images into memory) and flag you for a console ban.
EDIT:
Jesus christ, I just noticed that I spent an hour writing this XD so if you don't mind, I would be pleased and happy if you saved this PM in a text file or something, for future preferences.