ADAPTED FROM PRACTICAL REVERSE ENGINEERING BOOK

  • X86

  • ARM

  • THE WINDOWS KERNEL

x86 ARCHITECTURE CONCEPTS

  • BASIC THEORY
    • REGISTER PURPOSE
  • INSTRUCTION SET
    • SYNTAX
    • DATA MOVEMENT
    • ARITHMETIC OPERTAORS
    • STACK OPERATIONS
    • FUNCTION INVOCATION
    • CALLING CONVENTION

x86 BASIC THEORY

Posses eight 32-bit general purpose registers (GPRS)

EAX , EBX , ECX , EDX , EDI , ESI , EBP , and ESP

REGISTER PURPOSE


ECX : Counter in loops
ESI : Source in string/memory operations
EDI : Destination in string/memory operations
EBP : Base frame pointer
ESP : Stack pointer

The 32-bit EFLAGS register is used to store the status of arithmetic operations and other execution states (e.g., trap flag). For example, if the previous “add” operation resulted in a zero, the ZF flag will be set to 1. The flags in EFLAGS are primarily used to implement conditional branching.

In addition to the GPRs, EIP , and EFLAGS , there are also registers that control important low-level system mechanisms such as virtual memory, interrupts, and debugging. For example, CR0 controls whether paging is on or off, CR2 contains the linear address that caused a page fault, CR3 is the base address of a paging data structure, and CR4 controls the hardware virtualization settings. DR0 – DR7 are used to set memory breakpoints.

NOTE :

Although there are seven debug registers, the system allows only four mem-
ory breakpoints (DR0–DR3). The remaining registers are used for status.

INSTRUCTION SET

There are five types of movements.

■ Immediate to register
■ Register to register
■ Immediate to memory
■ Register to memory and vice versa
■ Memory to memory

NOTE

The first four methods are supported by all modern architectures, but the last
one is specific to x86.

SYNTAX


Depending on the assembler/disassembler, there are two syntax notations for x86 assembly code, Intel and AT&T: Intel

mov ecx, AABBCCDDh
mov ecx, [eax]
mov ecx, eax

AT&T

movl $0xAABBCCDD, %ecx
movl (%eax), %ecx
movl %eax, %ecx

It is important to note that these are the same instructions but written differently.

There are several differences between Intel and AT&T notation, but the most notable ones are as follows:

■ AT&T prefixes the register with % , and immediates with $ . Intel does not do this.

■ AT&T adds a prefix to the instruction to indicate operation width. For example, MOVL (long), MOVB (byte), etc. Intel does not do this.

■ AT&T puts the source operand before the destination. Intel reverses the order.

DATA MOVEMENT


Instuctions operate on values that come from register or main memory.

e.g.

mov esi, 0F003Fh   ; sets ESI = 0xF003
mov esi, ecx ; sets ESI = ECX

Similar to other assembly language conventions, x86 uses square brackets ( [ ] ) to indicate memory access. (The only exception to this is the LEA instruction, which uses [] but does not actually reference memory.)

mov   dword ptr [eax], 1
; set the memory at address EAX to 1
mov   ecx, [eax]
;set ECX to the value at address EAX
mov   [eax], ebx
; set the memory at address EAX to EBX
mov   [esi+34h], eax
;set the memory address at (ESI+34) to EAX
mov   eax, [esi+34h]
set EAX to the value at address (EAX+34)
mov   edx, [ecx+eax]
; set EDX to the value at address (ECX+EAX)

Pseudo C

*eax = 1;
ecx = *eax;
*eax = ebx;
*(esi+34) = eax;
eax = *(esi+34);
edx = *(ecx+eax);

Array type objects.

[Base + Index*scale]

mov    [edi+esi*8], eax

here EDI is the array base address .

ESI is the array index.

element size is 8.

01:           loop_start:
02: 8B 47 04       mov eax, [edi+4]
03: 8B 04 98       mov eax, [eax+ebx*4]
04: 85 C0          test eax, eax
...
05: 74 14          jz short loc_7F627F
06:             loc_7F627F:
07: 43             inc ebx
08: 3B 1F          cmp ebx, [edi]
09: 7C DD          jl short loop_start

line 2 reads a double-word from offset +4 from EDI and then uses it as a base address into the array in the next line.

line 7 increments the address.

line 8 compares the index against a value at offset +0 in the same structure.

typedef struct _Foo
{
		DWORD size;         // +0x00
		DOWRD array[...]    // +0x04
}FOO, *PFOO;

PFOO bar = ...;
for (i = ... ; i < bar->size; i++)
		if(bar->array[i] != 0){
		...
		}
}

The MOVSB/MOVSW/MOVSD instructions mov data 1, 2, or 4 byte between two memory addresses. They implicitly use EDI/ESI as destination/source addresses, respectively.

In addition they also update source/destination depending upon the directional flag DF in EFLAGS . If DF is set to 0, the addresses are decremented otherwise incremented.

These instructions are typically used to implement string or memory copy functions when the length is known at compile time. In some cases, they are accompanied by the REP prefix, which repeats an instruction up to ECX times.

ASSEMBLY

01: BE 28 B5 41 00    mov    esi, offset _RamdiskBoot
02: 8D BD 40 FF FF+   lea edi, [ebp-0C0h]
03: A5                movsd
04: A5                movsd
05: A5                movsd
06: A5                movsd

01: ESI = pointer to RamdiskBoot

02: EDI is an address somewhere on the stack

03: copies 4 bytes from EDI to ESI; increment each by 4

04 : same as above

05 : same as above

06 : same as above

PSEUDO C

/* a GUID is 16-byte structure */
GUID RamDiskBootDiskGuid = ...; // global
...
GUID foo;
memcpy(&foo, &RamdiskBootDiskGuid, sizeof(GUID));

NOTE:

02: 8D BD 40 FF FF+   lea edi, [ebp-0C0h]

Although LEA uses ' [ ] ' , it actually does not red from memory address. it simply evaluates the expression in the square brackets and puts it in the destination register.

for e.g here, if EBP was having an value of 0x1000, EDI will be 0xF40 i.e.(0x1000 - 0xC0)

REP prefix example.

ASSEMBLY

01: 6A 08             push    8
; push 8 on the stack
02: ...
03: 59                pop     ecx
; pop the stack. Basically sets ECX to 8.
04: ...
05: BE 00 44 61 00    mov     esi, offset _KeServiceDescriptorTable
06: BF C0 43 61 00    mov     edi, offset _KeServiceDescriptorTableShadow
07: F3 A5             rep     movsd
; copy 32 bytes (movsd repeated 8 times)
; from this we can deduce that whatever these two objects are, they are
; likely to be 32 bytes in size.

PSEUDO C

memcpy(&KeServiceDescriptorTableShadow, &KeServiceDescriptorTable, 32);

Another class of data movement instructions with implicit source and destination includes the SCAS and STOS instructions. Similar to MOVS , these instructions can operate at 1-, 2-, or 4-byte granularity. SCAS implicitly compares AL/AX/EAX with data starting at the memory address EDI ; EDI is automatically incremented/ decremented depending on the DF bit in EFLAGS . Given its semantic, SCAS is commonly used along with the REP prefix to find a byte, word, or double-word in a buffer. For example, the C strlen() function can be implemented as follows:

01: 30 C0           xor      al, al
;set AL to 0 (NUL byte).
02: 89 FB           mov      ebx, edi
; save the original pointer to the string
03: F2 AE           repne    scasb
;repeatedly scan forward one byte at a time as long as AL does not match the
;byte at EDI when this instruction ends, it means we reached the NUL byte in
;the string buffer
04: 29 DF           sub      edi, ebx
;edi is now the NUL byte location. Subtract that from the original pointer
;to the length.

STOS is the same as SCAS except that it writes the value AL/AX/EAX to EDI . It is commonly used to initialize a buffer to a constant value (such as memset() ).

01: 33 C0           xor       eax, eax
; set EAX to 0
02: 6A 09           push      9
; push 9 on the stack
03: 59              pop       ecx
; pop it back in ECX. Now ECX = 9.
04: 8B FE           mov       edi, esi
; set the destination address
05: F3 AB           rep     stosd
; write 36 bytes of zero to the destination buffer (STOSD repeated 9 times)
; this is equivalent lent to memset(edi, 0, 36)

LODS is another instruction from the same family. It reads a 1-, 2-, or 4-byte value from ESI and stores it in AL , AX , or EAX .

ARITHMETIC OPERATIONS


only multiplication and division have only some exceptions , reaming all mathematical operation bitwise operations.

add, subtract, increment , decrement

add    esp, 14h       ; esp = esp + 0x14
sub    ecx, eax       ; ecx = ecx - eax
inc    ecx            ; ecx = ecx + 1
dec    ecx            ; ecx = ecx - 1

and, or, xor, not

or    eax, 0FFFFFFFFh   ; eax = eax | 0xFFFFFFFF
and   ebx, 0Ch          ; ebx = ebx & 0xC
xor   eax, eax          ; eax = eax ^ eax
not   edi               ; edi = -edi

SHIFT

shl    eax, 4  ; eax = eax << 4
shr    eax, 4  ; eax = eax >> 4

ROTATE

rol    al, 3        ; rotate AL left 3 positions
ror    al, 1        ; rotate AL right 1 position

MULTIPLICATION

Unsigned and signed multiplication is done through the MUL and IMUL instructions, respectively. The MUL instruction has the following general form: MUL reg/memory. That is, it can only operate on register or memory values. The register is multiplied with AL, AX, or EAX and the result is stored in AX , DX:AX, or EDX:EAX, depending on the operand width.

The result is stored in EDX:EAX for 32-bit multiplication is because the result potentially may not fit in one 32-bit register.

IMUL has three forms:
■ IMUL reg/mem — Same as MUL
■ IMUL reg1, reg2/mem — reg1 = reg1 * reg2/mem
■ IMUL reg1, reg2/mem, imm — reg1 = reg2 * imm

imul		ecx 		; EDX:EAX = EAX * ECX
imul 		esi, 1A0h	; ESI = ESI * 0x1A0
imul 		ecx, esi 	; ECX = ECX * ESI

DIVISION

Unsigned and signed division is done through the DIV and IDIV instructions,respectively. They take only one parameter (divisor) and have the following form: DIV/IDIV reg/mem.
Depending on the divisor’s size, DIV will use either AX , DX:AX , or EDX:EAX as the dividend, and the resulting quotient/remainder pair are stored in AL/AH , AX/DX , or EAX/EDX .

STACK OPERATION


Fundamental data structure in programming languages and OS.
Stack is last in first out, with only two basic operations push and pop.
In x86 STACK is a contiguous memory region pointed by ESP and grows downwards.

; initial esp = 0xb20000
01:		mov		eax,0AAAAAAAAh
02:		mov		ebx,0BBBBBBBBh
03:		mov		ecx,0CCCCCCCCh
04:		mov		edx,0DDDDDDDDh
05:		push		eax
06:		push		ebx
07:		pop		esi
08:		pop		edi

after line 5:
address 0xb1fffc will contain the value 0xAAAAAAAA and ESP will be 0xb1fffc (=0xb20000-4)

after line 6:
address 0xb1fff8 will contain the value 0xBBBBBBBB and ESP will be 0xb1fff8 (=0xb1fffc-4)

after line 7:
esi will have the value of 0xBBBBBBBB and ESP will be at (0xb1fff8 + 4) = 0xb1fffc

after line 8:
edi will have the value of 0xAAAAAAAA and ESP will be at (0xb1fffc + 4) = 0xb20000

FUNCTION INVOCATION


Consider the following C code

int
__cdecl addme(short a, short b)
{
	return a+b;
}

ASSEMBLY

01:		push		ebp
02:		mov		ebp, esp
03:		....
04:		movsx		eax, word ptr [ebp+8]
05:		movsx		ecx, word ptr [ebp+0Ch]
06:		add		eax, ecx
07:		.....
08:		mov		esp, ebp
09:		pop		ebp
10:		retn
sum = addme(x, y);

ASSEMBLY

01:		push		eax
02:		...
03:		push		ecx
04:		call		addme
05:		add		esp, 8

The CALL instruction performs two operations:

  1. It pushes the return address (address immediately after the CALL instruc- tion) on the stack.
  2. It changes EIP to the call destination. This effectively transfers control to the call target and begins execution there.

RET simply pops the address stored on the top of the stack into EIP and trans- fers control to it.

CALLING CONVENTION


A calling convention is a set of rules dictating how function calls work at the machine level. It is defi ned by the Application Binary Interface (ABI) for a particular system. There are many calling conventions, but the popular ones are CDECL , STDCALL , THISCALL , and FASTCALL .

How is the function get called 1st eax and ecx register are being pushed into the stack and the call instruction is invoked, which immediately pushes the next address into the stack, i.e the address of the add esp, 8 line , and transfers the control to the addme function, to be more clear eip is pointed to the address of addme function.

Lets explain the function assembly line by line . on the 1st line base pointer, ebp is pushed into the stack.then the stack pointer is pointed to the base pointer. This two steps is known as function prologue.then the value at the offset [ebp + 0x8] is moved in eax register, same with ecx register with the value at offset [ebp + 0xc]. Then the add instruction is invoked eax = eax + ecx. Then the base pointer is pointed to the stack pointer and ebp is popped. These two steps is known as function epilogue. As ebp is popped, top of the stack contains the address which is being pushed when the addme function is called. clearly address of the add esp, 8 line.

ARM Fundamentals

  • BASIC FEATURES
    • DATA TYPES AND REGISTERS

BASIC FEATURES

ARM : ADVANCED RISC MACHINE

  • Instruction set is very small as compared to x86 but it has more GPRs.

  • Instruction length is fixed(16 or 32) depending upon the state.

  • It uses Load Store model for memory access.i.e data in memory cannot be directly manipulated, it must be moved to register to manipulate.-

  • It uses LDR and STR instructions, for performing an operation on a data stored in a memory we need to load it into a resgister operate and then store it back.-

  • It too provides privilege level(analogy ring 0 to ring 3 in x86).-

  • In ARM privilege levels is defined by eight different modes.

    • User (USR)
    • Fast interrupt request (FIQ)
    • Interrupt request (IRQ)
    • Supervisor (SVC)
    • Monitor (MON)
    • Abort (ABT)
    • Undefi ned (UND)
    • System (SYS)
  • ARM processor also operates in two states.

    • ARM state
    • Thumb state
  • In ARM state instructions are always 32 bit but in Thumb state it can be both 32bit and 16 bit.

  • 32 bit Thumb instructions have w. suffix.

  • ARM also supports conditional execution.

    • suppose there are two instructios 1,2, it is possible to manipulate that 2 will only be executed iff result of 1 is something desired.
  • Another ARM feature , barrel shifter.

    • MOV R1, R0, LSL #1 here R1 = R0 << 1 or R1 = R0 * 2

DATA TYPES AND REGISTERS


  • There are sixteen 32 bit GPRs(General purpose registers).

  • Ranging from R0,R1,...,R15.

  • The first 12 registers are for normal use.

  • R13 : it is called as the stack pointer(SP).(analogy RSP/ESP in x86/x64). R13 points to the top of the stack

  • R14 : it is called as the link register(LR).It normally holds the return address when the function is being called.In a code which doesnot use as LR to store the return address , it can be used as a GPR.

  • R15 : It is called as the program counter(PC).

    • PC points to the current running address + 8 in ARM state, and current running address + 4 in Thumb state .

    • Code can directly read from and write to PC. It will immediately cause its execution at the start of the address.

    • After line 2 is executed R0 will hold the value of 0x8346+4=0x834a

    • When directly reading from PC it follows as a normal program counter.

  • ARM stores information about the current execution state in the current program status register(CPSR).(Analogy EFLAGS)

THE WINDOWS KERNEL

  • WINDOWS FUNDAMENTALS
    • Memory Layout
    • Processor Initialization

WINDOWS FUNDAMENTALS

Memory Layout


-> Divides virtual address space in two space , kernel space and user space .
-> On x86 and ARM upper 2gb is reserved for kernel processes and lower 2 gb for user processes.
-> Virtual address in user space is from 0x00 to 0x7fffffff, and 0x80000000 to 0xffffffff.
-> x64 , user space from 0 to 0x000007ff'ffffffff and kernel space 0xffff0800'00000000 to above.
-> Running processes only have access to user space but kernel mode has access to both user space and kernel space.

Processor Initialization


When kernel boots up it performs some basic initialization for each processor.

The Processor control region (PCR)
-> per processor structure that stores critical information and state .
e.g: ox x86 it contains the base address of IDT and current IRQL.

IDT : The Interrupt Descriptor Table (IDT) is a data structure used by the x86 architecture to implement an interrupt vector table. The IDT is used by the processor to determine the correct response to interrupts and exceptions.

IRQL : An Interrupt Request Level (IRQL) is a hardware-independent means with which Windows prioritizes interrupts that come from the system's processors.

-> Inside PCR there is another data structure called processor region control block(PRCB). It is a per-processor structure that contains informationabout the processor , e.g CPU type, model, current thread that is running . next thread to run , queue of DPC.

DPC : A Deferred Procedure Call (DPC) is a Microsoft Windows operating system mechanism which allows high-priority tasks (e.g. an interrupt handler) to defer required but lower-priority tasks for later execution. This permits device drivers and other low-level event consumers to perform the high-priority part of their processing quickly, and schedule non-critical additional processing for execution at a lower priority.

The PCR for a current processor can only be accessed from kernel mode through some special registers.It is stored in the FS segment (x86), GS segment (x64), or one of the system coprocessor registers (ARM).

PsGetCurrentThread proc near
  mov   rax, gs:188h          ; gs:[0] is the PCR, offset 0x180 is the PRCB,
                              ; offset 0x8 into the PRCB is the CurrentThread
field
  retn
PsGetCurrentThread endp

PsGetCurrentProcess proc near
  mov   rax, gs:188h          ; get current thread (see above)
  mov   rax, [rax+0B8h]       ; offset 0x70 into the ETHREAD is the associated
                              ; process(actually ETHREAD.ApcState.Process)
  retn
PsGetCurrentProcess endp

CTF WRITEUPS

  • darkctf2020

  • phantomctf2020

  • redpwnctf202

darkCTF 2020

  • so_much
  • hw

so_much

link to file

its like an argv1 password check .

root@kali:~/ctf/darkctf2020/rev# ./so_much
Lets have an argument. Shall we?
root@kali:~/ctf/darkctf2020/rev# ./so_much qwerty
Nada. Not the right password!
*Psst the password is part of the flag*
root@kali:~/ctf/darkctf2020/rev#

analyzed with gdb

root@kali:~/ctf/darkctf2020/rev# gdb -q ./so_much
Reading symbols from ./so_much...
(No debugging symbols found in ./so_much)
gdb-peda$ info func
All defined functions:

Non-debugging symbols:
0x0000000000001000  _init
0x0000000000001080  __cxa_finalize@plt
0x0000000000001090  puts@plt
0x00000000000010a0  __stack_chk_fail@plt
0x00000000000010b0  printf@plt
0x00000000000010c0  strcmp@plt
0x00000000000010d0  strcat@plt
0x00000000000010e0  _start
0x0000000000001110  deregister_tm_clones
0x0000000000001140  register_tm_clones
0x0000000000001180  __do_global_dtors_aux
0x00000000000011c0  frame_dummy
0x00000000000011c9  main
0x0000000000001281  get_flag
0x0000000000001342  flag_48
0x0000000000001379  flag_49
0x00000000000013a4  flag_50
0x00000000000013cf  flag_51
0x00000000000013fa  flag_52
0x0000000000001425  flag_53
0x0000000000001450  flag_54
0x000000000000147b  flag_55
0x00000000000014a6  flag_56
0x00000000000014d1  flag_57
0x00000000000014fc  flag_97
0x0000000000001527  flag_98
0x0000000000001552  flag_99
0x000000000000157d  flag_100
0x00000000000015a8  flag_101
0x00000000000015d3  flag_102
0x00000000000015fe  flag_103
0x0000000000001629  flag_104
0x0000000000001654  flag_105
0x000000000000167f  flag_106
0x00000000000016aa  flag_107
0x00000000000016d5  flag_108
0x0000000000001700  flag_109
0x000000000000172b  flag_110
0x0000000000001762  flag_111
0x000000000000178d  flag_112
0x00000000000017b8  flag_113
0x00000000000017e3  flag_114
0x000000000000180e  flag_115
0x000000000000183f  flag_116
0x000000000000186a  flag_117
0x0000000000001895  flag_118
0x00000000000018c0  flag_119
0x00000000000018f1  flag_120
0x000000000000191c  flag_121
0x0000000000001947  flag_122
0x0000000000001972  flag_95
0x00000000000019a9  flag_123
0x00000000000019d4  flag_125
0x0000000000001a00  __libc_csu_init
0x0000000000001a70  __libc_csu_fini
0x0000000000001a78  _fini
gdb-peda$

there are so many functions for flag checking i guess.

lets look at disassembly of main function

   0x00005555555551c9 <+0>:     endbr64
   0x00005555555551cd <+4>:     push   rbp
   0x00005555555551ce <+5>:     mov    rbp,rsp
   0x00005555555551d1 <+8>:     sub    rsp,0x20
   0x00005555555551d5 <+12>:    mov    DWORD PTR [rbp-0x14],edi
   0x00005555555551d8 <+15>:    mov    QWORD PTR [rbp-0x20],rsi
   0x00005555555551dc <+19>:    mov    rax,QWORD PTR fs:0x28
   0x00005555555551e5 <+28>:    mov    QWORD PTR [rbp-0x8],rax
   0x00005555555551e9 <+32>:    xor    eax,eax
   0x00005555555551eb <+34>:    lea    rax,[rip+0xe16]        # 0x555555556008
   0x00005555555551f2 <+41>:    mov    QWORD PTR [rbp-0x10],rax
   0x00005555555551f6 <+45>:    lea    rax,[rbp-0x10]
   0x00005555555551fa <+49>:    mov    rdi,rax
   0x00005555555551fd <+52>:    call   0x555555555281 <get_flag>
   0x0000555555555202 <+57>:    cmp    DWORD PTR [rbp-0x14],0x2
   0x0000555555555206 <+61>:    jne    0x55555555525a <main+145>
   0x0000555555555208 <+63>:    mov    rdx,QWORD PTR [rbp-0x10]
   0x000055555555520c <+67>:    mov    rax,QWORD PTR [rbp-0x20]
   0x0000555555555210 <+71>:    add    rax,0x8
   0x0000555555555214 <+75>:    mov    rax,QWORD PTR [rax]
   0x0000555555555217 <+78>:    mov    rsi,rdx
   0x000055555555521a <+81>:    mov    rdi,rax
   0x000055555555521d <+84>:    call   0x5555555550c0 <strcmp@plt>
   0x0000555555555222 <+89>:    test   eax,eax
   0x0000555555555224 <+91>:    jne    0x55555555524c <main+131>
   0x0000555555555226 <+93>:    mov    rax,QWORD PTR [rbp-0x10]
   0x000055555555522a <+97>:    mov    rsi,rax
   0x000055555555522d <+100>:   lea    rdi,[rip+0xdd5]        # 0x555555556009
   0x0000555555555234 <+107>:   mov    eax,0x0
   0x0000555555555239 <+112>:   call   0x5555555550b0 <printf@plt>
   0x000055555555523e <+117>:   lea    rdi,[rip+0xdcf]        # 0x555555556014
   0x0000555555555245 <+124>:   call   0x555555555090 <puts@plt>
   0x000055555555524a <+129>:   jmp    0x555555555266 <main+157>
   0x000055555555524c <+131>:   lea    rdi,[rip+0xddd]        # 0x555555556030
   0x0000555555555253 <+138>:   call   0x555555555090 <puts@plt>
   0x0000555555555258 <+143>:   jmp    0x555555555266 <main+157>
   0x000055555555525a <+145>:   lea    rdi,[rip+0xe17]        # 0x555555556078
   0x0000555555555261 <+152>:   call   0x555555555090 <puts@plt>
   0x0000555555555266 <+157>:   mov    eax,0x0
   0x000055555555526b <+162>:   mov    rcx,QWORD PTR [rbp-0x8]
   0x000055555555526f <+166>:   xor    rcx,QWORD PTR fs:0x28
   0x0000555555555278 <+175>:   je     0x55555555527f <main+182>
   0x000055555555527a <+177>:   call   0x5555555550a0 <__stack_chk_fail@plt>
   0x000055555555527f <+182>:   leave  
   0x0000555555555280 <+183>:   ret    
End of assembler dump.

If we look closely there is only 1 cmp and test. i think if we bypass that we can get the flag.

lets talk about the compare

0x0000555555555202 <+57>:    cmp    DWORD PTR [rbp-0x14],0x2

its just checking that the number of arguments passes is 2 or not. so we need not to bypass it, just we will give a argument it will be checked.

lets come to test

0x0000555555555222 <+89>:    test   eax,eax

lets bypass it

gdb-peda$ b *0x0000555555555222
Breakpoint 2 at 0x555555555222
gdb-peda$ c
Continuing.
Breakpoint 2, 0x0000555555555222 in main ()
gdb-peda$ info reg
rax            0xfffffff6          0xfffffff6
rbx            0x0                 0x0
rcx            0xffff7ffd          0xffff7ffd
rdx            0x7b                0x7b
rsi            0x7fffffffe020      0x7fffffffe020
rdi            0x7fffffffe4ad      0x7fffffffe4ad
rbp            0x7fffffffe0a0      0x7fffffffe0a0
rsp            0x7fffffffe080      0x7fffffffe080
r8             0x0                 0x0
r9             0x7fffffffe020      0x7fffffffe020
r10            0x3                 0x3
r11            0x2                 0x2
r12            0x5555555550e0      0x5555555550e0
r13            0x0                 0x0
r14            0x0                 0x0
r15            0x0                 0x0
rip            0x555555555222      0x555555555222 <main+89>
eflags         0x297               [ CF PF AF SF IF ]
cs             0x33                0x33
ss             0x2b                0x2b
ds             0x0                 0x0
es             0x0                 0x0
fs             0x0                 0x0
gs             0x0                 0x0
gdb-peda$ set $eax=0
gdb-peda$ c
Continuing.
darkCTF{w0w_s0_m4ny_funct10ns}
WoW! so much revving...
[Inferior 1 (process 11828) exited normally]
Warning: not running
gdb-peda$

FLAG : darkCTF{w0w_s0_m4ny_funct10ns}

HW

link to file

root@kali:~/ctf/darkctf2020/rev# ./hw
Enter the right arguments
root@kali:~/ctf/darkctf2020/rev# ./hw qwe
Enter the right arguments
root@kali:~/ctf/darkctf2020/rev# ./hw hi hello
invalid argument: hi
root@kali:~/ctf/darkctf2020/rev#

it checks on 3 arguments.

root@kali:~/ctf/darkctf2020/rev# gdb -q ./hw
Reading symbols from ./hw...
(No debugging symbols found in ./hw)
gdb-peda$ info func
All defined functions:

Non-debugging symbols:
0x0000000000001000  _init
0x00000000000010a0  __cxa_finalize@plt
0x00000000000010b0  putchar@plt
0x00000000000010c0  puts@plt
0x00000000000010d0  pow@plt
0x00000000000010e0  __stack_chk_fail@plt
0x00000000000010f0  printf@plt
0x0000000000001100  strcmp@plt
0x0000000000001110  sprintf@plt
0x0000000000001120  _start
0x0000000000001150  deregister_tm_clones
0x0000000000001180  register_tm_clones
0x00000000000011c0  __do_global_dtors_aux
0x0000000000001200  frame_dummy
0x0000000000001209  main
0x00000000000012b6  print
0x00000000000014c5  check
0x0000000000001630  __libc_csu_init
0x00000000000016a0  __libc_csu_fini
0x00000000000016a8  _fini
gdb-peda$ b *main
Breakpoint 1 at 0x1209
gdb-peda$ r hi hello
Starting program: /root/ctf/darkctf2020/rev/hw hi hello
[----------------------------------registers-----------------------------------]
RAX: 0x555555555209 (<main>:    endbr64)
RBX: 0x0
RCX: 0x7ffff7e62718 --> 0x7ffff7e64b00 --> 0x0
RDX: 0x7fffffffe1c8 --> 0x7fffffffe4c9 ("SHELL=/bin/bash")
RSI: 0x7fffffffe1a8 --> 0x7fffffffe4a3 ("/root/ctf/darkctf2020/rev/hw")
RDI: 0x3
RBP: 0x555555555630 (<__libc_csu_init>: endbr64)
RSP: 0x7fffffffe0b8 --> 0x7ffff7ccacca (<__libc_start_main+234>:        mov    edi,eax)
RIP: 0x555555555209 (<main>:    endbr64)
R8 : 0x0
R9 : 0x7ffff7fe2180 (<_dl_fini>:        push   rbp)
R10: 0x3
R11: 0x2
R12: 0x555555555120 (<_start>:  endbr64)
R13: 0x0
R14: 0x0
R15: 0x0
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x5555555551f9 <__do_global_dtors_aux+57>:   nop    DWORD PTR [rax+0x0]
   0x555555555200 <frame_dummy>:        endbr64
   0x555555555204 <frame_dummy+4>:      jmp    0x555555555180 <register_tm_clones>
=> 0x555555555209 <main>:       endbr64
   0x55555555520d <main+4>:     push   rbp
   0x55555555520e <main+5>:     mov    rbp,rsp
   0x555555555211 <main+8>:     sub    rsp,0x10
   0x555555555215 <main+12>:    mov    DWORD PTR [rbp-0x4],edi
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe0b8 --> 0x7ffff7ccacca (<__libc_start_main+234>:       mov    edi,eax)
0008| 0x7fffffffe0c0 --> 0x7fffffffe1a8 --> 0x7fffffffe4a3 ("/root/ctf/darkctf2020/rev/hw")
0016| 0x7fffffffe0c8 --> 0x300000000
0024| 0x7fffffffe0d0 --> 0x555555555209 (<main>:        endbr64)
0032| 0x7fffffffe0d8 --> 0x7ffff7cca7d9 (<init_cacheinfo+297>:  mov    rbp,rax)
0040| 0x7fffffffe0e0 --> 0x0
0048| 0x7fffffffe0e8 --> 0x5542342e7c1aef74
0056| 0x7fffffffe0f0 --> 0x555555555120 (<_start>:      endbr64)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 1, 0x0000555555555209 in main ()
gdb-peda$ disas
Dump of assembler code for function main:
=> 0x0000555555555209 <+0>:     endbr64
   0x000055555555520d <+4>:     push   rbp
   0x000055555555520e <+5>:     mov    rbp,rsp
   0x0000555555555211 <+8>:     sub    rsp,0x10
   0x0000555555555215 <+12>:    mov    DWORD PTR [rbp-0x4],edi
   0x0000555555555218 <+15>:    mov    QWORD PTR [rbp-0x10],rsi
   0x000055555555521c <+19>:    cmp    DWORD PTR [rbp-0x4],0x3
   0x0000555555555220 <+23>:    je     0x555555555230 <main+39>
   0x0000555555555222 <+25>:    lea    rdi,[rip+0xddf]        # 0x555555556008
   0x0000555555555229 <+32>:    call   0x5555555550c0 <puts@plt>
   0x000055555555522e <+37>:    jmp    0x5555555552af <main+166>
   0x0000555555555230 <+39>:    mov    rax,QWORD PTR [rbp-0x10]
   0x0000555555555234 <+43>:    add    rax,0x8
   0x0000555555555238 <+47>:    mov    rax,QWORD PTR [rax]
   0x000055555555523b <+50>:    mov    esi,0x1
   0x0000555555555240 <+55>:    mov    rdi,rax
   0x0000555555555243 <+58>:    call   0x5555555554c5 <check>
   0x0000555555555248 <+63>:    test   eax,eax
   0x000055555555524a <+65>:    jne    0x555555555290 <main+135>
   0x000055555555524c <+67>:    mov    rax,QWORD PTR [rbp-0x10]
   0x0000555555555250 <+71>:    add    rax,0x10
   0x0000555555555254 <+75>:    mov    rax,QWORD PTR [rax]
   0x0000555555555257 <+78>:    mov    esi,0x2
   0x000055555555525c <+83>:    mov    rdi,rax
   0x000055555555525f <+86>:    call   0x5555555554c5 <check>
   0x0000555555555264 <+91>:    test   eax,eax
   0x0000555555555266 <+93>:    jne    0x55555555526f <main+102>
   0x0000555555555268 <+95>:    call   0x5555555552b6 <print>
   0x000055555555526d <+100>:   jmp    0x5555555552af <main+166>
   0x000055555555526f <+102>:   mov    rax,QWORD PTR [rbp-0x10]
   0x0000555555555273 <+106>:   add    rax,0x10
   0x0000555555555277 <+110>:   mov    rax,QWORD PTR [rax]
   0x000055555555527a <+113>:   mov    rsi,rax
   0x000055555555527d <+116>:   lea    rdi,[rip+0xd9e]        # 0x555555556022
   0x0000555555555284 <+123>:   mov    eax,0x0
   0x0000555555555289 <+128>:   call   0x5555555550f0 <printf@plt>
   0x000055555555528e <+133>:   jmp    0x5555555552af <main+166>
   0x0000555555555290 <+135>:   mov    rax,QWORD PTR [rbp-0x10]
   0x0000555555555294 <+139>:   add    rax,0x8
   0x0000555555555298 <+143>:   mov    rax,QWORD PTR [rax]
   0x000055555555529b <+146>:   mov    rsi,rax
   0x000055555555529e <+149>:   lea    rdi,[rip+0xd7d]        # 0x555555556022
   0x00005555555552a5 <+156>:   mov    eax,0x0
   0x00005555555552aa <+161>:   call   0x5555555550f0 <printf@plt>
   0x00005555555552af <+166>:   mov    eax,0x0
   0x00005555555552b4 <+171>:   leave  
   0x00005555555552b5 <+172>:   ret    
End of assembler dump.
gdb-peda$

there are two 'test'

.
.
0x0000555555555248 <+63>:    test   eax,eax
.
.
0x0000555555555264 <+91>:    test   eax,eax
.
.

lets bypass them and see if we can get the flag or not.

gdb-peda$ b *0x0000555555555248
Breakpoint 2 at 0x555555555248
gdb-peda$ b *0x0000555555555264
Breakpoint 3 at 0x555555555264
gdb-peda$ c
Continuing.
[----------------------------------registers-----------------------------------]
RAX: 0xffffffe0
RBX: 0x0
RCX: 0xffffffff
RDX: 0x68 ('h')
RSI: 0x0
RDI: 0x7fffffffe082 --> 0x690000306c6c3348 ('H3ll0')
RBP: 0x7fffffffe0b0 --> 0x555555555630 (<__libc_csu_init>:      endbr64)
RSP: 0x7fffffffe0a0 --> 0x7fffffffe1a8 --> 0x7fffffffe4a3 ("/root/ctf/darkctf2020/rev/hw")
RIP: 0x555555555248 (<main+63>: test   eax,eax)
R8 : 0xffffffff
R9 : 0x1
R10: 0x0
R11: 0x0
R12: 0x555555555120 (<_start>:  endbr64)
R13: 0x0
R14: 0x0
R15: 0x0
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x55555555523b <main+50>:    mov    esi,0x1
   0x555555555240 <main+55>:    mov    rdi,rax
   0x555555555243 <main+58>:    call   0x5555555554c5 <check>
=> 0x555555555248 <main+63>:    test   eax,eax
   0x55555555524a <main+65>:    jne    0x555555555290 <main+135>
   0x55555555524c <main+67>:    mov    rax,QWORD PTR [rbp-0x10]
   0x555555555250 <main+71>:    add    rax,0x10
   0x555555555254 <main+75>:    mov    rax,QWORD PTR [rax]
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe0a0 --> 0x7fffffffe1a8 --> 0x7fffffffe4a3 ("/root/ctf/darkctf2020/rev/hw")
0008| 0x7fffffffe0a8 --> 0x300000000
0016| 0x7fffffffe0b0 --> 0x555555555630 (<__libc_csu_init>:     endbr64)
0024| 0x7fffffffe0b8 --> 0x7ffff7ccacca (<__libc_start_main+234>:       mov    edi,eax)
0032| 0x7fffffffe0c0 --> 0x7fffffffe1a8 --> 0x7fffffffe4a3 ("/root/ctf/darkctf2020/rev/hw")
0040| 0x7fffffffe0c8 --> 0x300000000
0048| 0x7fffffffe0d0 --> 0x555555555209 (<main>:        endbr64)
0056| 0x7fffffffe0d8 --> 0x7ffff7cca7d9 (<init_cacheinfo+297>:  mov    rbp,rax)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 2, 0x0000555555555248 in main ()
gdb-peda$ set $eax=0
gdb-peda$ c
Continuing.
[----------------------------------registers-----------------------------------]
RAX: 0xffffffef
RBX: 0x0
RCX: 0xfffffff7
RDX: 0x68 ('h')
RSI: 0x0
RDI: 0x7fffffffe082 --> 0x690000646c723057 ('W0rld')
RBP: 0x7fffffffe0b0 --> 0x555555555630 (<__libc_csu_init>:      endbr64)
RSP: 0x7fffffffe0a0 --> 0x7fffffffe1a8 --> 0x7fffffffe4a3 ("/root/ctf/darkctf2020/rev/hw")
RIP: 0x555555555264 (<main+91>: test   eax,eax)
R8 : 0xffffffff
R9 : 0x1
R10: 0x0
R11: 0x0
R12: 0x555555555120 (<_start>:  endbr64)
R13: 0x0
R14: 0x0
R15: 0x0
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x555555555257 <main+78>:    mov    esi,0x2
   0x55555555525c <main+83>:    mov    rdi,rax
   0x55555555525f <main+86>:    call   0x5555555554c5 <check>
=> 0x555555555264 <main+91>:    test   eax,eax
   0x555555555266 <main+93>:    jne    0x55555555526f <main+102>
   0x555555555268 <main+95>:    call   0x5555555552b6 <print>
   0x55555555526d <main+100>:   jmp    0x5555555552af <main+166>
   0x55555555526f <main+102>:   mov    rax,QWORD PTR [rbp-0x10]
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe0a0 --> 0x7fffffffe1a8 --> 0x7fffffffe4a3 ("/root/ctf/darkctf2020/rev/hw")
0008| 0x7fffffffe0a8 --> 0x300000000
0016| 0x7fffffffe0b0 --> 0x555555555630 (<__libc_csu_init>:     endbr64)
0024| 0x7fffffffe0b8 --> 0x7ffff7ccacca (<__libc_start_main+234>:       mov    edi,eax)
0032| 0x7fffffffe0c0 --> 0x7fffffffe1a8 --> 0x7fffffffe4a3 ("/root/ctf/darkctf2020/rev/hw")
0040| 0x7fffffffe0c8 --> 0x300000000
0048| 0x7fffffffe0d0 --> 0x555555555209 (<main>:        endbr64)
0056| 0x7fffffffe0d8 --> 0x7ffff7cca7d9 (<init_cacheinfo+297>:  mov    rbp,rax)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 3, 0x0000555555555264 in main ()
gdb-peda$ set $eax=0
gdb-peda$ c
Continuing.
darkCTF{4rgum3nts_are_v3ry_1mp0rt4nt!!!}
[Inferior 1 (process 7645) exited normally]
Warning: not running
gdb-peda$

we got the flag

FLAG : darkCTF{4rgum3nts_are_v3ry_1mp0rt4nt!!!}

PHANTOM CTF

  • REVSENG

  • S3CRET

REVSENG

link to file

root@kali:~/ctf/phantomctf/rev# r2 -A revseng
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Check for objc references
[x] Check for vtables
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information
[x] Use -AA or aaaa to perform additional experimental analysis.
 -- bash: r3: command not found
[0x00001060]> afl
0x00001060    1 42           entry0
0x00001090    4 41   -> 34   sym.deregister_tm_clones
0x000010c0    4 57   -> 51   sym.register_tm_clones
0x00001100    5 57   -> 50   entry.fini0
0x00001140    1 5            entry.init0
0x00001000    3 23           sym._init
0x00001360    1 1            sym.__libc_csu_fini
0x00001364    1 9            sym._fini
0x000011a9    1 334          sym.print
0x00001040    1 6            sym.imp.malloc
0x00001030    1 6            sym.imp.printf
0x00001300    4 93           sym.__libc_csu_init
0x0000117e    4 43           sym.foo
0x00001145    4 57           main
[0x00001060]>

print function has the flag, so lets attack it.

[0x00001060]> s sym.print
[0x000011a9]> pdf
            ; CALL XREF from main @ 0x1166
┌ 334: sym.print ();
│           ; var void *var_10h @ rbp-0x10
│           ; var char var_6h @ rbp-0x6
│           ; var char var_5h @ rbp-0x5
│           ; var char *format @ rbp-0x4
│           ; var char var_3h @ rbp-0x3
│           ; var char var_2h @ rbp-0x2
│           ; var char var_1h @ rbp-0x1
│           0x000011a9      55             push rbp                    ; /src:29
│           0x000011aa      4889e5         mov rbp, rsp
│           0x000011ad      4883ec10       sub rsp, 0x10
│           0x000011b1      c645ff70       mov byte [var_1h], 0x70     ; /src:31 ; 'p'
│           0x000011b5      c645fe43       mov byte [var_2h], 0x43     ; /src:32 ; 'C'
│           0x000011b9      c645fd54       mov byte [var_3h], 0x54     ; /src:33 ; 'T'
│           0x000011bd      c645fc46       mov byte [format], 0x46     ; /src:34 ; 'F'
│           0x000011c1      c645fb7b       mov byte [var_5h], 0x7b     ; /src:35 ; '{'
│           0x000011c5      c645fa7d       mov byte [var_6h], 0x7d     ; /src:36 ; '}'
│           0x000011c9      bf15000000     mov edi, 0x15               ; /src:37 ; size_t size
│           0x000011ce      e86dfeffff     call sym.imp.malloc         ;  void *malloc(size_t size)
│           0x000011d3      488945f0       mov qword [var_10h], rax
│           0x000011d7      488b45f0       mov rax, qword [var_10h]    ; /src:38
│           0x000011db      c60077         mov byte [rax], 0x77        ; 'w'
│                                                                      ; [0x77:1]=0                                                                                        
│           0x000011de      488b45f0       mov rax, qword [var_10h]    ; /src:39
│           0x000011e2      4883c001       add rax, 1
│           0x000011e6      c60033         mov byte [rax], 0x33        ; '3'
│                                                                      ; [0x33:1]=0                                                                                        
│           0x000011e9      488b45f0       mov rax, qword [var_10h]    ; /src:40
│           0x000011ed      4883c002       add rax, 2
│           0x000011f1      c60063         mov byte [rax], 0x63        ; 'c'
│                                                                      ; [0x63:1]=0                                                                                        
│           0x000011f4      488b45f0       mov rax, qword [var_10h]    ; /src:41
│           0x000011f8      4883c003       add rax, 3
│           0x000011fc      c6006f         mov byte [rax], 0x6f        ; 'o'
│                                                                      ; [0x6f:1]=0                                                                                        
│           0x000011ff      488b45f0       mov rax, qword [var_10h]    ; /src:42
│           0x00001203      4883c004       add rax, 4
│           0x00001207      c6006e         mov byte [rax], 0x6e        ; 'n'
│                                                                      ; [0x6e:1]=0                                                                                        
│           0x0000120a      488b45f0       mov rax, qword [var_10h]    ; /src:43
│           0x0000120e      4883c005       add rax, 5
│           0x00001212      c60037         mov byte [rax], 0x37        ; '7'
│                                                                      ; [0x37:1]=0                                                                                        
│           0x00001215      488b45f0       mov rax, qword [var_10h]    ; /src:44
│           0x00001219      4883c006       add rax, 6
│           0x0000121d      c60072         mov byte [rax], 0x72        ; 'r'
│                                                                      ; [0x72:1]=0                                                                                        
│           0x00001220      488b45f0       mov rax, qword [var_10h]    ; /src:45
│           0x00001224      4883c007       add rax, 7
│           0x00001228      c60030         mov byte [rax], 0x30        ; '0'
│                                                                      ; [0x30:1]=0                                                                                        
│           0x0000122b      488b45f0       mov rax, qword [var_10h]    ; /src:46
│           0x0000122f      4883c008       add rax, 8
│           0x00001233      c6006c         mov byte [rax], 0x6c        ; 'l'
│                                                                      ; [0x6c:1]=0                                                                                        
│           0x00001236      488b45f0       mov rax, qword [var_10h]    ; /src:47
│           0x0000123a      4883c009       add rax, 9
│           0x0000123e      c60074         mov byte [rax], 0x74        ; 't'
│                                                                      ; [0x74:1]=0                                                                                        
│           0x00001241      488b45f0       mov rax, qword [var_10h]    ; /src:48
│           0x00001245      4883c00a       add rax, 0xa
│           0x00001249      c60068         mov byte [rax], 0x68        ; 'h'
│                                                                      ; [0x68:1]=104                                                                                      
│           0x0000124c      488b45f0       mov rax, qword [var_10h]    ; /src:49
│           0x00001250      4883c00b       add rax, 0xb
│           0x00001254      c60033         mov byte [rax], 0x33        ; '3'
│                                                                      ; [0x33:1]=0                                                                                        
│           0x00001257      488b45f0       mov rax, qword [var_10h]    ; /src:50
│           0x0000125b      4883c00c       add rax, 0xc
│           0x0000125f      c60062         mov byte [rax], 0x62        ; 'b'
│                                                                      ; [0x62:1]=0                                                                                        
│           0x00001262      488b45f0       mov rax, qword [var_10h]    ; /src:51
│           0x00001266      4883c00d       add rax, 0xd
│           0x0000126a      c60031         mov byte [rax], 0x31        ; '1'
│                                                                      ; [0x31:1]=0                                                                                        
│           0x0000126d      488b45f0       mov rax, qword [var_10h]    ; /src:52
│           0x00001271      4883c00e       add rax, 0xe
│           0x00001275      c6006e         mov byte [rax], 0x6e        ; 'n'
│                                                                      ; [0x6e:1]=0                                                                                        
│           0x00001278      488b45f0       mov rax, qword [var_10h]    ; /src:53
│           0x0000127c      4883c00f       add rax, 0xf
│           0x00001280      c60061         mov byte [rax], 0x61        ; 'a'
│                                                                      ; [0x61:1]=2                                                                                        
│           0x00001283      488b45f0       mov rax, qword [var_10h]    ; /src:54
│           0x00001287      4883c010       add rax, 0x10
│           0x0000128b      c60072         mov byte [rax], 0x72        ; 'r'
│                                                                      ; [0x72:1]=0                                                                                        
│           0x0000128e      488b45f0       mov rax, qword [var_10h]    ; /src:55
│           0x00001292      4883c011       add rax, 0x11
│           0x00001296      c60069         mov byte [rax], 0x69        ; 'i'
│                                                                      ; [0x69:1]=2                                                                                        
│           0x00001299      488b45f0       mov rax, qword [var_10h]    ; /src:56
│           0x0000129d      4883c012       add rax, 0x12
│           0x000012a1      c60033         mov byte [rax], 0x33        ; '3'
│                                                                      ; [0x33:1]=0                                                                                        
│           0x000012a4      488b45f0       mov rax, qword [var_10h]    ; /src:57
│           0x000012a8      4883c013       add rax, 0x13
│           0x000012ac      c60073         mov byte [rax], 0x73        ; 's'
│                                                                      ; [0x73:1]=0                                                                                        
│           0x000012af      488b45f0       mov rax, qword [var_10h]    ; /src:58
│           0x000012b3      4883c014       add rax, 0x14
│           0x000012b7      c60000         mov byte [rax], 0
│           0x000012ba      0fbe75fa       movsx esi, byte [var_6h]    ; /src:59
│           0x000012be      440fbe45fb     movsx r8d, byte [var_5h]
│           0x000012c3      0fbe7dfc       movsx edi, byte [format]
│           0x000012c7      0fbe4dfd       movsx ecx, byte [var_3h]
│           0x000012cb      0fbe55fe       movsx edx, byte [var_2h]
│           0x000012cf      0fbe45ff       movsx eax, byte [var_1h]
│           0x000012d3      56             push rsi
│           0x000012d4      ff75f0         push qword [var_10h]
│           0x000012d7      4589c1         mov r9d, r8d
│           0x000012da      4189f8         mov r8d, edi
│           0x000012dd      89c6           mov esi, eax
│           0x000012df      488d3d1e0d00.  lea rdi, str.c_c_c_c_c_s_c  ; 0x2004 ; "%c%c%c%c%c%s%c\n" ; const char *format
│           0x000012e6      b800000000     mov eax, 0
│           0x000012eb      e840fdffff     call sym.imp.printf         ; int printf(const char *format)
│           0x000012f0      4883c410       add rsp, 0x10
│           0x000012f4      90             nop                         ; /src:60
│           0x000012f5      c9             leave
└           0x000012f6      c3             ret
[0x000011a9]>

I just wrote a simple angr script.

import angr

value = 0

p = angr.Project("./revseng")
func_addr = p.loader.find_symbol("print").rebased_addr
cl = p.factory.callable(func_addr)
cl(value)                         
print(cl.result_state.posix.stdout.concretize())
root@kali:~/ctf/phantomctf/rev# python3 aa.py
WARNING | 2020-11-24 09:01:23,072 | cle.loader | The main binary is a position-independent executable. It is being loaded with a base address of 0x400000.
WARNING | 2020-11-24 09:01:23,917 | angr.state_plugins.symbolic_memory | The program is accessing memory or registers with an unspecified value. This could indicate unwanted behavior.
WARNING | 2020-11-24 09:01:23,917 | angr.state_plugins.symbolic_memory | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:
WARNING | 2020-11-24 09:01:23,917 | angr.state_plugins.symbolic_memory | 1) setting a value to the initial state
WARNING | 2020-11-24 09:01:23,917 | angr.state_plugins.symbolic_memory | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null
WARNING | 2020-11-24 09:01:23,917 | angr.state_plugins.symbolic_memory | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY_REGISTERS}, to suppress these messages.
WARNING | 2020-11-24 09:01:23,917 | angr.state_plugins.symbolic_memory | Filling register rbp with 8 unconstrained bytes referenced from 0x4011a9 (print+0x0 in revseng (0x11a9))
WARNING | 2020-11-24 09:01:26,375 | angr.state_plugins.symbolic_memory | Filling memory at 0xc0000015 with 235 unconstrained bytes referenced from 0x556db0 (printf+0x0 in libc.so.6 (0x56db0))
[b'pCTF{w3con7r0lth3b1nari3s}\n']

S3CRET

a .pyc file was given

link to file

root@kali:~/ctf/phantomctf/rev# uncompyle6 s3cr3t.pyc
# uncompyle6 version 3.7.3
# Python bytecode 3.7 (3394)
# Decompiled from: Python 2.7.17 (default, Jan 19 2020, 19:54:54)
# [GCC 9.2.1 20200110]
# Warning: this version of Python has problems handling the Python 3 "byte" type in constants properly.

# Embedded file name: source.py
# Compiled at: 2020-08-18 14:40:36
# Size of source mod 2**32: 741 bytes


def kraitrot(input, d):
    Lf = input[0:d]
    Ls = input[d:]
    return Ls + Lf


def cobraverse(s):
    g = ''
    g += s[1::2]
    g += s[0::2]
    return g


def vipershift(s):
    g = ''
    for i in range(len(s)):
        a = hex(ord(s[i]) + 20)[2:]
        g += a

    return g


s3rc3t = input("Enter the secret to get access to python's cave : ")
if len(s3rc3t) < 28:
    print('Add little more weight :::\n')
else:
    if vipershift(cobraverse(kraitrot(s3rc3t, 15))) == '867387738d7c8284688f454745737c4488894784884491575a807a738787':
        print("\nWhy does Python live on land?\nBecause it's above C-level . XD!! \nCongrats for the flag anyways")
    else:
        print('Maybe a python bit you , better luck next time :((')
# okay decompiling s3cr3t.pyc

SOLUTION

#!/usr/bin/env python3
# -*- coding : utf-8 -*-


# 867387738d7c8284688f454745737c4488894784884491575a807a738787
#l[0] = 0x86 - 20
l = [114, 95, 115, 95, 121, 104, 110, 112, 84, 123, 49, 51, 49, 95, 104, 48, 116, 117, 51, 112, 116, 48, 125, 67, 70, 108, 102, 95, 115, 115]

st = ''
for i in l:
    st += chr(i)

s1 = st[:15]
s2 = st[15:]


f1 = ''

for i in range(15):
    f1 += s2[i]
    f1 += s1[i]
flag = ''
flag = f1[15:] + f1[:15]

print(flag)
root@kali:~/ctf/phantomctf/rev# ./s3c_solve.py
pCTF{l1f3_1s_sh0rt_us3_pyth0n}
root@kali:~/ctf/phantomctf/rev# ./s3cr3t.pyc
Enter the secret to get access to python's cave : pCTF{l1f3_1s_sh0rt_us3_pyth0n}

Why does Python live on land?
Because it's above C-level . XD!!
Congrats for the flag anyways
root@kali:~/ctf/phantomctf/rev#

REDPWN CTF 2020

  • ROPES

  • BUBBLY

ROPES

link to file

root@kali:~/ctf/redpwn/rev# strings ropes
__PAGEZERO
__TEXT
__text
__TEXT
__stubs
__TEXT
__stub_helper
__TEXT
__cstring
__TEXT
__unwind_info
__TEXT
__DATA
__nl_symbol_ptr
__DATA
__la_symbol_ptr
__DATA
__LINKEDIT
/usr/lib/dyld
/usr/lib/libSystem.B.dylib
Give me a magic number:
'First part is: flag{r0pes_ar3_
Second part is: just_l0ng_str1ngs}'
@dyld_stub_binder
@_printf
@_puts
@_scanf
_mh_execute_header
!main
__mh_execute_header
_main
_printf
_puts
_scanf
dyld_stub_binder
root@kali:~/ctf/redpwn/rev#

BUBBLY

link to file

root@kali:~/ctf/redpwn/rev# file bubbly
bubbly: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=edb56d2d9355bcee01909f171d8a272a3e82d053, with debug_info, not stripped
root@kali:~/ctf/redpwn/rev# ./bubbly
I hate my data structures class! Why can't I just sort by hand?
1
2
1111
Try again!
root@kali:~/ctf/redpwn/rev#

There were 3 functions , main, check, print_flag.

int main(void)

{
  uint32_t i;
  int unused;
  Bool pass;

  setbuf(stdout,(char *)0x0)
  setbuf(stdin,(char *)0x0);
  setbuf(stderr,(char *)0x0);
  puts("I hate my data structures class! Why can\'t I just sort by hand?");
  pass = false;
  while( true ) {
    __isoc99_scanf(&DAT_00102058);
    if (8 < i) break;
    nums[i] = nums[i] ^ nums[i + 1];
    nums[i + 1] = nums[i + 1] ^ nums[i];
    nums[i] = nums[i] ^ nums[i + 1];
    pass = check();
  }
  if (pass == false) {
    puts("Try again!");
  }
  else {
    puts("Well done!");
    print_flag();
  }
  return 0;
}

_Bool check(void)

{
  uint32_t i;
  _Bool pass;

  i = 0;
  while( true ) {
    if (8 < i) {
      return true;
    }
    if (nums[i + 1] < nums[i]) break;
    i = i + 1;
  }
  return false;
}

print_flag is just printing the flag

there is an predefined array nums of size 10.

gdb-peda$ x/24w nums
0x555555558060 <nums>:  0x00000001      0x0000000a      0x00000003      0x00000002
0x555555558070 <nums+16>:       0x00000005      0x00000009      0x00000008      0x00000007
0x555555558080 <nums+32>:       0x00000004      0x00000006      0x00000000      0x00000000

nums = [1,10,3,2,5,9,8,7,4,6]

whatever value we are giving it is swapping it with the next value, if we give an input greater than 8 it ends the while loop and checks the array nums is sorted or not , if it is sorted then it will print the flag.There are so many solutions for this question.

root@kali:~/ctf/redpwn/rev# nc 2020.redpwnc.tf 31039
I hate my data structures class! Why can't I just sort by hand?
1
2
3
4
5
6
7
8
1
4
5
6
7
4
5
6
4
3
5
10
Well done!
flag{4ft3r_y0u_put_u54c0_0n_y0ur_c011ege_4pp5_y0u_5t1ll_h4ve_t0_d0_th15_57uff}
root@kali:~/ctf/redpwn/rev#

BSIDES MAHARASTRA

  • File

  • Login App

File


    Challenge
    11 Solves

File
100

Author :- Vibhu Bansal

link to file

root@kali:~/ctf/bsidesmh/rev# file file_-_Vibhu_Bansal
file_-_Vibhu_Bansal: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, Go BuildID=v1Iv2nQi31NDwFtWqyYe/wXLgARnjy_BmqFgOKixW/AywtSac820tpDw2BaA9j/h_s0a_dHBmMZT0Ia_LNJ, not stripped
root@kali:~/ctf/bsidesmh/rev# ./file_-_Vibhu_Bansal
Welcome , to Key Exchange Portal
Please Enter your Key: 1234
root@kali:~/ctf/bsidesmh/rev#

It was a Go-lang build file .

i used ghidra to see decompiled of main.main()


void main.main(void)

{
  undefined **ppuVar1;
  long *plVar2;
  long **pplVar3;
  long in_FS_OFFSET;
  undefined *puStack16;

  while (ppuVar1 = (undefined **)(*(long *)(in_FS_OFFSET + 0xfffffff8) + 0x10),
        &puStack16 < *ppuVar1 || &puStack16 == (undefined **)*ppuVar1) {
    runtime.morestack_noctxt();
  }
  puStack16 = &UNK_004e94b0;
  fmt.Fprintln();
  pplVar3 = os.Stdout;
  fmt.Fprint();
  runtime.newobject();
  fmt.Fscanln();
  plVar2 = *pplVar3;
  if ((((pplVar3[1] == (long *)0xe) && (*plVar2 == 0x6173736575676e75)) &&
      (*(int *)(plVar2 + 1) == 0x31656c62)) && (*(short *)((long)plVar2 + 0xc) == 0x3332)) {
    fmt.Fprintln();
  }
  return;
}

we can see it comparing with the hex values.

unguessable123

root@kali:~/ctf/bsidesmh/rev# ./file_-_Vibhu_Bansal
Welcome , to Key Exchange Portal
Please Enter your Key: unguessable123
czNtcGwzX3IzdjNyczMK

It gave us some sort of key . it was just b64 encoded.

root@kali:~/ctf/bsidesmh/rev# echo "czNtcGwzX3IzdjNyczMK" | base64 -d
s3mpl3_r3v3rs3

flag : BMH{s3mpl3_r3v3rs3}

Login App


    Challenge
    12 Solves

Login App
200

"Admin share me this as an alternative to a web login. Is it really secure. "

Author :- Saumya Agrawal

link to file

root@kali:~/ctf/bsidesmh/rev# file Login_App
Login_App: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=3507aa01d32c34dc8e8c6462b764adb90a82768d, stripped
root@kali:~/ctf/bsidesmh/rev# ./Login_App

        .__  __.   .        .  .   .              .   ,       
        [__)(__ * _| _  __  |\/| _.|_  _.._. _. __|_ -+-._. _.
        [__).__)|(_](/,_)   |  |(_][ )(_][  (_]_) [ ) | [  (_]



        1> Login
        2> Get Flag
        0> exit

> 2
Enter 4 digit auth code : 1234
Wrong Code !!
root@kali:~/ctf/bsidesmh/rev#

I did some basic static analysis, and saw the strings which are coming are not there in the file . it was a packed binary , but i was unable to detect packing . so i just used gdb to generate a core file while running

root@kali:~/ctf/bsidesmh/rev# gdb -q ./Login_App
Reading symbols from ./Login_App...
(No debugging symbols found in ./Login_App)
gdb-peda$ catch syscall exit_group
Catchpoint 1 (syscall 'exit_group' [231])
gdb-peda$ r
Starting program: /root/ctf/bsidesmh/rev/Login_App
[Attaching after process 52294 fork to child process 52298]
[New inferior 2 (process 52298)]
[Detaching after fork from parent process 52294]
[Inferior 1 (process 52294) detached]
process 52298 is executing new program: /root/ctf/bsidesmh/rev/Login_App
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

        .__  __.   .        .  .   .              .   ,       
        [__)(__ * _| _  __  |\/| _.|_  _.._. _. __|_ -+-._. _.
        [__).__)|(_](/,_)   |  |(_][ )(_][  (_]_) [ ) | [  (_]



        1> Login
        2> Get Flag
        0> exit

> 2
Enter 4 digit auth code : 1234
Wrong Code !!
gdb-peda$ generate-core-file ffff
Saved corefile ffff
gdb-peda$ quit
root@kali:~/ctf/bsidesmh/rev# strings ffff | grep BMH
BMH{c4n_y0u_g3t_1n51d333}Tc
BMH{c4n_y0u_g3t_1n51d333}
BMH{c4n_y0u_g3t_1n51d333}
root@kali:~/ctf/bsidesmh/rev#

easy-peasy.

flag : BMH{c4n_y0u_g3t_1n51d333}

PESUCTF 2021

  • Comparinator

  • Opertaion

  • Return

  • Snake

  • Z3al

comparinator

link to file

C decompile using ghidra


undefined8 main(uint param_1,long param_2)

{
  undefined8 uVar1;
  long in_FS_OFFSET;
  int local_7c;
  uint local_78 [4];
  uint local_68;
  uint local_64;
  uint local_60;
  uint local_5c;
  uint local_58;
  uint local_54;
  uint local_50;
  uint local_4c;
  uint local_48;
  uint local_44;
  uint local_40;
  uint local_3c;
  uint local_38;
  uint local_34;
  uint local_30;
  uint local_2c;
  uint local_28;
  uint local_24;
  uint local_20;
  uint local_1c;
  uint local_18;
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  if (param_1 == 0x1a) {
    local_7c = 0;
    while (local_7c < 0x19) {
      __isoc99_sscanf(*(undefined8 *)(param_2 + ((long)local_7c + 1) * 8),&DAT_00102004,
                      local_78 + local_7c);
      local_7c = local_7c + 1;
    }
    if (local_78[0] != 0x72) {
      printf("%d invalid\n",(ulong)local_78[0]);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_78[1] != 0x31) {
      printf("%d invalid\n",(ulong)local_78[1]);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_78[2] != 0x67) {
      printf("%d invalid\n",(ulong)local_78[2]);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_78[3] != 0x68) {
      printf("%d invalid\n",(ulong)local_78[3]);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_68 != 0x74) {
      printf("%d invalid\n",(ulong)local_68);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_64 != 0x5f) {
      printf("%d invalid\n",(ulong)local_64);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_60 != 0x68) {
      printf("%d invalid\n",(ulong)local_60);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_5c != 0x33) {
      printf("%d invalid\n",(ulong)local_5c);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_58 != 0x72) {
      printf("%d invalid\n",(ulong)local_58);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_54 != 0x33) {
      printf("%d invalid\n",(ulong)local_54);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_50 != 0x5f) {
      printf("%d invalid\n",(ulong)local_50);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_4c != 0x74) {
      printf("%d invalid\n",(ulong)local_4c);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_48 != 0x68) {
      printf("%d invalid\n",(ulong)local_48);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_44 != 0x65) {
      printf("%d invalid\n",(ulong)local_44);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_40 != 0x5f) {
      printf("%d invalid\n",(ulong)local_40);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_3c != 0x77) {
      printf("%d invalid\n",(ulong)local_3c);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_38 != 0x68) {
      printf("%d invalid\n",(ulong)local_38);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_34 != 0x30) {
      printf("%d invalid\n",(ulong)local_34);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_30 != 0x6c) {
      printf("%d invalid\n",(ulong)local_30);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_2c != 0x65) {
      printf("%d invalid\n",(ulong)local_2c);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_28 != 0x5f) {
      printf("%d invalid\n",(ulong)local_28);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_24 != 0x74) {
      printf("%d invalid\n",(ulong)local_24);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_20 != 0x31) {
      printf("%d invalid\n",(ulong)local_20);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_1c != 0x6d) {
      printf("%d invalid\n",(ulong)local_1c);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    if (local_18 != 0x33) {
      printf("%d invalid\n",(ulong)local_18);
      uVar1 = 1;
      goto LAB_001015fd;
    }
    puts("valid");
  }
  else {
    printf("invalid %d\n",(ulong)param_1);
  }
  uVar1 = 0;
LAB_001015fd:
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return uVar1;
}
>>> s = [0x72,0x31,0x67,0x68,0x74,0x5f,0x68,0x33,0x72,0x33,0x5f,0x74,0x68,0x65,0x5f,0x77,0x68,0x30,0x6c,0x65,0x5f,0x74,0x31,0x6d,0x33]
>>> for i in s:
...     print(chr(i),end='')
... 
r1ght_h3r3_the_wh0le_t1m3>>> 
>>> 
$ ./comparinator r 1 g h t _ h 3 r 3 _ t h e _ w h 0 l e _ t 1 m 3
0 invalid

FLAG : pesuctf{r1ght_h3r3_the_wh0le_t1m3}

OPERATION

link to file

Question : What will be the input if output is 2svj153vum


undefined8 main(void)

{
  undefined local_1a [10];
  char *local_10;
  
  setbuf(stdout,(char *)0x0);
  setbuf(stdin,(char *)0x0);
  setbuf(stderr,(char *)0x0);
  local_10 = (char *)malloc(0xb);
  __isoc99_scanf("%[^\n]%*c",local_1a);
  local_10 = (char *)operation(local_1a);
  puts(local_10);
  return 0;
}


void * operation(char *param_1)

{
  size_t sVar1;
  ulong uVar2;
  char local_44 [11];
  char local_39;
  int local_38;
  char local_31;
  void *local_30;
  int local_24;
  int local_20;
  int local_1c;
  
  local_30 = malloc(0xb);
  local_1c = 0;
  while( true ) {
    uVar2 = SEXT48(local_1c);
    sVar1 = strlen(param_1);
    if (sVar1 <= uVar2) break;
    if ((param_1[local_1c] < 'a') || ('z' < param_1[local_1c])) {
      local_44[local_1c] = param_1[local_1c];
    }
    else {
      local_31 = param_1[local_1c] + '\x0f';
      if (local_31 < '{') {
        local_44[local_1c] = local_31;
      }
      else {
        local_38 = 0x7a - param_1[local_1c];
        local_39 = (char)local_38 + '_';
        local_44[local_1c] = local_39;
      }
    }
    local_1c = local_1c + 1;
  }
  local_20 = 0;
  sVar1 = strlen(local_44);
  local_24 = (int)sVar1 + -2;
  while (-1 < local_24) {
    *(char *)((long)local_24 + (long)local_30) = local_44[local_20];
    *(char *)((long)local_24 + 1 + (long)local_30) = local_44[local_20 + 1];
    local_20 = local_20 + 2;
    local_24 = local_24 + -2;
  }
  return local_30;
}

So i wrote a python script which completely reverses the code

#!/usr/bin/env python3

out = '2svj153vum'
r1 = ''
for i in range(8,-1,-2):
	r1 += out[i]
	r1 += out[i+1]
# print(r1)

flag = 'pesuctf{'

for i in r1:
	if i in '0123456789':
		flag += i
	elif ord(i)-15 > ord('a') :
		flag += chr(ord(i)-15)
	else:
		flag += chr(122 - ord(i) + 95 )
flag += '}'
print(flag)
$ ./operation.py 
pesuctf{fl3g15go2d}

FLAG : pesuctf{fl3g15go2d}

RETURN

link to file

the question said what does the function RETURN

if we check the disassembly of main

0x0000555555555298 <+0>:	push   rbp
   0x0000555555555299 <+1>:	mov    rbp,rsp
   0x000055555555529c <+4>:	sub    rsp,0x20
   0x00005555555552a0 <+8>:	mov    rax,QWORD PTR [rip+0x2e01]        # 0x5555555580a8 <stdout@@GLIBC_2.2.5>
   0x00005555555552a7 <+15>:	mov    esi,0x0
   0x00005555555552ac <+20>:	mov    rdi,rax
   0x00005555555552af <+23>:	call   0x5555555550b0 <setbuf@plt>
   0x00005555555552b4 <+28>:	mov    rax,QWORD PTR [rip+0x2dc5]        # 0x555555558080 <stdin@@GLIBC_2.2.5>
   0x00005555555552bb <+35>:	mov    esi,0x0
   0x00005555555552c0 <+40>:	mov    rdi,rax
   0x00005555555552c3 <+43>:	call   0x5555555550b0 <setbuf@plt>
   0x00005555555552c8 <+48>:	mov    rax,QWORD PTR [rip+0x2dd1]        # 0x5555555580a0 <stderr@@GLIBC_2.2.5>
   0x00005555555552cf <+55>:	mov    esi,0x0
   0x00005555555552d4 <+60>:	mov    rdi,rax
   0x00005555555552d7 <+63>:	call   0x5555555550b0 <setbuf@plt>
   0x00005555555552dc <+68>:	lea    rax,[rbp-0x1c]
   0x00005555555552e0 <+72>:	mov    rsi,rax
   0x00005555555552e3 <+75>:	lea    rdi,[rip+0xd1f]        # 0x555555556009
   0x00005555555552ea <+82>:	mov    eax,0x0
   0x00005555555552ef <+87>:	call   0x5555555550d0 <__isoc99_scanf@plt>
   0x00005555555552f4 <+92>:	movzx  eax,BYTE PTR [rbp-0x1c]
   0x00005555555552f8 <+96>:	cmp    al,0x63
   0x00005555555552fa <+98>:	jne    0x55555555535c <main+196>
   0x00005555555552fc <+100>:	movzx  eax,BYTE PTR [rbp-0x1b]
   0x0000555555555300 <+104>:	cmp    al,0x61
   0x0000555555555302 <+106>:	jne    0x55555555535c <main+196>
   0x0000555555555304 <+108>:	movzx  eax,BYTE PTR [rbp-0x1a]
   0x0000555555555308 <+112>:	cmp    al,0x6e
   0x000055555555530a <+114>:	jne    0x55555555535c <main+196>
   0x000055555555530c <+116>:	movzx  eax,BYTE PTR [rbp-0x19]
   0x0000555555555310 <+120>:	cmp    al,0x64
   0x0000555555555312 <+122>:	jne    0x55555555535c <main+196>
   0x0000555555555314 <+124>:	movzx  eax,BYTE PTR [rbp-0x18]
   0x0000555555555318 <+128>:	cmp    al,0x79
   0x000055555555531a <+130>:	jne    0x55555555535c <main+196>
   0x000055555555531c <+132>:	movzx  eax,BYTE PTR [rbp-0x17]
   0x0000555555555320 <+136>:	cmp    al,0x5f
   0x0000555555555322 <+138>:	jne    0x55555555535c <main+196>
   0x0000555555555324 <+140>:	movzx  eax,BYTE PTR [rbp-0x16]
   0x0000555555555328 <+144>:	cmp    al,0x69
   0x000055555555532a <+146>:	jne    0x55555555535c <main+196>
   0x000055555555532c <+148>:	movzx  eax,BYTE PTR [rbp-0x15]
   0x0000555555555330 <+152>:	cmp    al,0x73
   0x0000555555555332 <+154>:	jne    0x55555555535c <main+196>
   0x0000555555555334 <+156>:	movzx  eax,BYTE PTR [rbp-0x14]
   0x0000555555555338 <+160>:	cmp    al,0x5f
   0x000055555555533a <+162>:	jne    0x55555555535c <main+196>
   0x000055555555533c <+164>:	movzx  eax,BYTE PTR [rbp-0x13]
   0x0000555555555340 <+168>:	cmp    al,0x6e
   0x0000555555555342 <+170>:	jne    0x55555555535c <main+196>
   0x0000555555555344 <+172>:	movzx  eax,BYTE PTR [rbp-0x12]
   0x0000555555555348 <+176>:	cmp    al,0x69
   0x000055555555534a <+178>:	jne    0x55555555535c <main+196>
   0x000055555555534c <+180>:	movzx  eax,BYTE PTR [rbp-0x11]
   0x0000555555555350 <+184>:	cmp    al,0x63
   0x0000555555555352 <+186>:	jne    0x55555555535c <main+196>
   0x0000555555555354 <+188>:	movzx  eax,BYTE PTR [rbp-0x10]
   0x0000555555555358 <+192>:	cmp    al,0x65
   0x000055555555535a <+194>:	je     0x555555555377 <main+223>
   0x000055555555535c <+196>:	lea    rdi,[rip+0xcaf]        # 0x555555556012
   0x0000555555555363 <+203>:	mov    eax,0x0
   0x0000555555555368 <+208>:	call   0x555555555030 <printf@plt>
   0x000055555555536d <+213>:	mov    edi,0x1
   0x0000555555555372 <+218>:	call   0x555555555050 <exit@plt>
   0x0000555555555377 <+223>:	mov    DWORD PTR [rbp-0x4],0x0
   0x000055555555537e <+230>:	jmp    0x5555555553d5 <main+317>
   0x0000555555555380 <+232>:	mov    eax,DWORD PTR [rbp-0x4]
   0x0000555555555383 <+235>:	cdqe   
   0x0000555555555385 <+237>:	movzx  eax,BYTE PTR [rbp+rax*1-0x1c]
   0x000055555555538a <+242>:	and    eax,0x1
   0x000055555555538d <+245>:	test   al,al
   0x000055555555538f <+247>:	jne    0x5555555553d1 <main+313>
   0x0000555555555391 <+249>:	mov    eax,DWORD PTR [rbp-0x4]
   0x0000555555555394 <+252>:	cdqe   
   0x0000555555555396 <+254>:	movzx  eax,BYTE PTR [rbp+rax*1-0x1c]
   0x000055555555539b <+259>:	cmp    al,0x60
   0x000055555555539d <+261>:	jle    0x5555555553c7 <main+303>
   0x000055555555539f <+263>:	mov    eax,DWORD PTR [rbp-0x4]
   0x00005555555553a2 <+266>:	cdqe   
   0x00005555555553a4 <+268>:	movzx  eax,BYTE PTR [rbp+rax*1-0x1c]
   0x00005555555553a9 <+273>:	cmp    al,0x7a
   0x00005555555553ab <+275>:	jg     0x5555555553c7 <main+303>
   0x00005555555553ad <+277>:	mov    eax,DWORD PTR [rbp-0x4]
   0x00005555555553b0 <+280>:	cdqe   
   0x00005555555553b2 <+282>:	movzx  eax,BYTE PTR [rbp+rax*1-0x1c]
   0x00005555555553b7 <+287>:	sub    eax,0x20
   0x00005555555553ba <+290>:	mov    edx,eax
   0x00005555555553bc <+292>:	mov    eax,DWORD PTR [rbp-0x4]
   0x00005555555553bf <+295>:	cdqe   
   0x00005555555553c1 <+297>:	mov    BYTE PTR [rbp+rax*1-0x1c],dl
   0x00005555555553c5 <+301>:	jmp    0x5555555553d1 <main+313>
   0x00005555555553c7 <+303>:	mov    eax,DWORD PTR [rbp-0x4]
   0x00005555555553ca <+306>:	cdqe   
   0x00005555555553cc <+308>:	mov    BYTE PTR [rbp+rax*1-0x1c],0x5f
   0x00005555555553d1 <+313>:	add    DWORD PTR [rbp-0x4],0x1
   0x00005555555553d5 <+317>:	mov    eax,DWORD PTR [rbp-0x4]
   0x00005555555553d8 <+320>:	cdqe   
   0x00005555555553da <+322>:	movzx  eax,BYTE PTR [rbp+rax*1-0x1c]
   0x00005555555553df <+327>:	test   al,al
   0x00005555555553e1 <+329>:	jne    0x555555555380 <main+232>
   0x00005555555553e3 <+331>:	lea    rdi,[rip+0xc2d]        # 0x555555556017
   0x00005555555553ea <+338>:	call   0x555555555040 <puts@plt>
   0x00005555555553ef <+343>:	lea    rax,[rbp-0x1c]
   0x00005555555553f3 <+347>:	mov    rdi,rax
   0x00005555555553f6 <+350>:	call   0x5555555551d5 <function2>
   0x00005555555553fb <+355>:	mov    QWORD PTR [rbp-0x10],rax
   0x00005555555553ff <+359>:	mov    eax,0x0
   0x0000555555555404 <+364>:	leave  
   0x0000555555555405 <+365>:	ret    
End of assembler dump.

It is checking the input as candy_is_nice then doing some calulation and calling the function2. So we just have to grab the return value of the function. in x86/x64 the return value of a function is stored in EAX/RAX register.

so we just set a breakpoint at main+355 next to the function call.

(gdb) b *0x00005555555553fb
Breakpoint 2 at 0x5555555553fb: file rev1.c, line 89.
(gdb) c
Continuing.
candy_is_nice
Cool

Breakpoint 2, 0x00005555555553fb in main () at rev1.c:89
89	in rev1.c
(gdb) x/s $rax
0x5555555592a0:	"`5a55d10766af2b4ee965bcd9923aa8a4398bbe13`"
(gdb) 

FLAG : pesuctf{5a55d10766af2b4ee965bcd9923aa8a4398bbe13}

snake

link to file

C decompile code using ghidra

MAIN

undefined8 main(EVP_PKEY_CTX *param_1,int param_2)

{
  undefined8 uVar1;
  
  init(param_1);
  layout();
  play();
  uVar1 = stdscr;
  wgetch();
  kill((__pid_t)uVar1,param_2);
  return 0;
}

There were so many functions, basically it a snake which we play on nokia 3310.

layout2 function was interesting


void layout2(void)

{
  int iVar1;
  size_t sVar2;
  
  iVar1 = centrex;
  sVar2 = strlen("_nOt_foUnd}");
  iVar1 = (iVar1 - (int)(sVar2 >> 1)) + 2;
  mvprintw(centrey,iVar1,"_nOt_foUnd}",iVar1);
  iVar1 = centrex;
  sVar2 = strlen("pesuctf{h0mE");
  iVar1 = (iVar1 - (int)sVar2) + 1;
  mvprintw(centrey,iVar1,"pesuctf{h0mE",iVar1);
  return;
}

mvprintw : this function takes 3 params , x and y coordinate of the screen , and the data to be printed.

(int)(sVar2 >> 1)) + 2 evaluating came as 7. so from where i can easily guess the flag.

FLAG : pesuctf{h0mE_foUnd}

Z3AL

link to file

From the name we can easily understand there will be so many functions, whic we have to solve to get the flag.

undefined8 FUN_00101b90(int param_1,undefined8 *param_2)

{
  char *__s;
  int iVar1;
  size_t sVar2;
  
  if (param_1 < 2) {
    printf("Usage: %s <key>\n",*param_2);
  }
  else {
    __s = (char *)param_2[1];
    sVar2 = strlen(__s);
    if ((int)sVar2 == 0x26) {
      iVar1 = FUN_00101159(__s);
      if (iVar1 == 0) {
        puts(":(");
      }
      else {
        puts(":)");
      }
    }
    else {
      puts(":(");
    }
  }
  return 0;
}

from main we got that the flag length is 0x26.


undefined8 FUN_00101159(byte *param_1)

{
  undefined8 uVar1;
  
  if (((((((byte)(param_1[4] ^ *param_1 ^ param_1[2]) == 0x60) &&
         ((byte)(param_1[8] ^ param_1[4] ^ param_1[6]) == 0x36)) &&
        ((byte)(param_1[0xc] ^ param_1[8] ^ param_1[10]) == 0x71)) &&
       (((((byte)(param_1[0x10] ^ param_1[0xc] ^ param_1[0xe]) == 0x32 &&
          ((byte)(param_1[0x14] ^ param_1[0x10] ^ param_1[0x12]) == 0x3f)) &&
         (((byte)(param_1[0x18] ^ param_1[0x14] ^ param_1[0x16]) == 1 &&
          (((byte)(param_1[0x1c] ^ param_1[0x18] ^ param_1[0x1a]) == 0x2a &&
           ((byte)(param_1[0x20] ^ param_1[0x1c] ^ param_1[0x1e]) == 0x3f)))))) &&
        (((byte)(param_1[0x24] ^ param_1[0x20] ^ param_1[0x22]) == 0x7a &&
         (((((byte)(param_1[5] ^ param_1[1] ^ param_1[3]) == 100 &&
            ((byte)(param_1[9] ^ param_1[5] ^ param_1[7]) == 0x7e)) &&
           ((byte)(param_1[0xd] ^ param_1[9] ^ param_1[0xb]) == 0x74)) &&
          (((param_1[0xd] ^ param_1[0xf]) == param_1[0x11] &&
           ((byte)(param_1[0x15] ^ param_1[0x11] ^ param_1[0x13]) == 0x58)))))))))) &&
      (((((byte)(param_1[0x19] ^ param_1[0x15] ^ param_1[0x17]) == 0x62 &&
         (((byte)(param_1[0x1d] ^ param_1[0x19] ^ param_1[0x1b]) == 0x5b &&
          ((byte)(param_1[0x21] ^ param_1[0x1d] ^ param_1[0x1f]) == 0x5c)))) &&
        ((byte)(param_1[0x25] ^ param_1[0x21] ^ param_1[0x23]) == 0x62)) &&
       ((((((((byte)(param_1[3] ^ *param_1 ^ param_1[1]) == 0x60 &&
             ((byte)(param_1[6] ^ param_1[3] ^ param_1[4]) == 0x70)) &&
            ((byte)(param_1[9] ^ param_1[6] ^ param_1[7]) == 0x6c)) &&
           (((byte)(param_1[0xc] ^ param_1[9] ^ param_1[10]) == 0x33 &&
            ((byte)(param_1[0xf] ^ param_1[0xc] ^ param_1[0xd]) == 0x68)))) &&
          (((byte)(param_1[0x12] ^ param_1[0xf] ^ param_1[0x10]) == 0x3f &&
           (((byte)(param_1[0x15] ^ param_1[0x12] ^ param_1[0x13]) == 99 &&
            ((byte)(param_1[0x18] ^ param_1[0x15] ^ param_1[0x16]) == 0x58)))))) &&
         ((byte)(param_1[0x1b] ^ param_1[0x18] ^ param_1[0x19]) == 0x34)) &&
        ((((byte)(param_1[0x1e] ^ param_1[0x1b] ^ param_1[0x1c]) == 0x75 &&
          ((byte)(param_1[0x21] ^ param_1[0x1e] ^ param_1[0x1f]) == 0x37)) &&
         ((byte)(param_1[0x24] ^ param_1[0x21] ^ param_1[0x22]) == 0x6e)))))))) &&
     (((((((byte)(param_1[4] ^ param_1[1] ^ param_1[2]) == 0x75 &&
          ((byte)(param_1[7] ^ param_1[4] ^ param_1[5]) == 0x6c)) &&
         (((byte)(param_1[10] ^ param_1[7] ^ param_1[8]) == 0x3d &&
          (((byte)(param_1[0xd] ^ param_1[10] ^ param_1[0xb]) == 0x70 &&
           ((byte)(param_1[0x10] ^ param_1[0xd] ^ param_1[0xe]) == 0x34)))))) &&
        ((byte)(param_1[0x13] ^ param_1[0x10] ^ param_1[0x11]) == 0x5a)) &&
       (((((((byte)(param_1[0x16] ^ param_1[0x13] ^ param_1[0x14]) == 1 &&
            ((byte)(param_1[0x19] ^ param_1[0x16] ^ param_1[0x17]) == 10)) &&
           ((byte)(param_1[0x1c] ^ param_1[0x19] ^ param_1[0x1a]) == 0x2d)) &&
          ((((byte)(param_1[0x1f] ^ param_1[0x1c] ^ param_1[0x1d]) == 0x43 &&
            ((byte)(param_1[0x22] ^ param_1[0x1f] ^ param_1[0x20]) == 0x27)) &&
           (((byte)(param_1[0x25] ^ param_1[0x22] ^ param_1[0x23]) == 0x3f &&
            (((byte)(param_1[6] ^ *param_1 ^ param_1[4]) == 0x75 &&
             ((byte)(param_1[10] ^ param_1[4] ^ param_1[8]) == 0x25)))))))) &&
         ((byte)(param_1[0xe] ^ param_1[8] ^ param_1[0xc]) == 0x34)) &&
        ((((((byte)(param_1[0x12] ^ param_1[0xc] ^ param_1[0x10]) == 0x66 &&
            ((byte)(param_1[0x16] ^ param_1[0x10] ^ param_1[0x14]) == 4)) &&
           ((byte)(param_1[0x1a] ^ param_1[0x14] ^ param_1[0x18]) == 0x36)) &&
          (((byte)(param_1[0x1e] ^ param_1[0x18] ^ param_1[0x1c]) == 0x76 &&
           ((byte)(param_1[0x22] ^ param_1[0x1c] ^ param_1[0x20]) == 0x3b)))) &&
         ((byte)(param_1[7] ^ param_1[1] ^ param_1[5]) == 0x6a)))))) &&
      (((((byte)(param_1[0xb] ^ param_1[5] ^ param_1[9]) == 0x31 &&
         ((byte)(param_1[0xf] ^ param_1[9] ^ param_1[0xd]) == 0x2e)) &&
        (((byte)(param_1[0x13] ^ param_1[0xd] ^ param_1[0x11]) == 0x5e &&
         ((((byte)(param_1[0x17] ^ param_1[0x11] ^ param_1[0x15]) == 10 &&
           ((byte)(param_1[0x1b] ^ param_1[0x15] ^ param_1[0x19]) == 0x33)) &&
          ((byte)(param_1[0x1f] ^ param_1[0x19] ^ param_1[0x1d]) == 6)))))) &&
       ((int)(char)(param_1[0x21] ^ param_1[0x1d]) != (uint)(param_1[0x23] == 0x40))))))) {
    uVar1 = 1;
  }
  else {
    uVar1 = 0;
  }
  return uVar1;
}

So i just wrote a simple z3 python script to solve the question.


#!/usr/bin/env python3

from z3 import *


flag = [BitVec(f"flag[{i}]",8) for i in range(0x26)]
s = Solver()
s.add(flag[37]==125)
s.add(flag[4] ^ flag[0] ^ flag[2] == 0x60 )
s.add(flag[8] ^ flag[4] ^ flag[6] == 0x36 )
s.add(flag[0xc] ^ flag[8] ^ flag[10] == 0x71 )
s.add(flag[0x10] ^ flag[0xc] ^ flag[0xe] == 0x32 )
s.add(flag[0x14] ^ flag[0x10] ^ flag[0x12] == 0x3f )
s.add(flag[0x18] ^ flag[0x14] ^ flag[0x16] == 1 )
s.add(flag[0x1c] ^ flag[0x18] ^ flag[0x1a] == 0x2a )
s.add(flag[0x20] ^ flag[0x1c] ^ flag[0x1e] == 0x3f )
s.add(flag[0x24] ^ flag[0x20] ^ flag[0x22] == 0x7a )
s.add(flag[5] ^ flag[1] ^ flag[3] == 100 )
s.add(flag[9] ^ flag[5] ^ flag[7] == 0x7e )
s.add(flag[0xd] ^ flag[9] ^ flag[0xb] == 0x74 )
s.add(flag[0xd] ^ flag[0xf] == flag[0x11] )
s.add(flag[0x15] ^ flag[0x11] ^ flag[0x13] == 0x58 )
s.add(flag[0x19] ^ flag[0x15] ^ flag[0x17] == 0x62 )
s.add(flag[0x1d] ^ flag[0x19] ^ flag[0x1b] == 0x5b )
s.add(flag[0x21] ^ flag[0x1d] ^ flag[0x1f] == 0x5c )
s.add(flag[0x25] ^ flag[0x21] ^ flag[0x23] == 0x62 )
s.add(flag[3] ^ flag[0] ^ flag[1] == 0x60 )
s.add(flag[6] ^ flag[3] ^ flag[4] == 0x70 )
s.add(flag[9] ^ flag[6] ^ flag[7] == 0x6c )
s.add(flag[0xc] ^ flag[9] ^ flag[10] == 0x33 )
s.add(flag[0xf] ^ flag[0xc] ^ flag[0xd] == 0x68 )
s.add(flag[0x12] ^ flag[0xf] ^ flag[0x10] == 0x3f )
s.add(flag[0x15] ^ flag[0x12] ^ flag[0x13] == 99 )
s.add(flag[0x18] ^ flag[0x15] ^ flag[0x16] == 0x58 )
s.add(flag[0x1b] ^ flag[0x18] ^ flag[0x19] == 0x34 )
s.add(flag[0x1e] ^ flag[0x1b] ^ flag[0x1c] == 0x75 )
s.add(flag[0x21] ^ flag[0x1e] ^ flag[0x1f] == 0x37 )
s.add(flag[0x24] ^ flag[0x21] ^ flag[0x22] == 0x6e )
s.add(flag[4] ^ flag[1] ^ flag[2] == 0x75 )
s.add(flag[7] ^ flag[4] ^ flag[5] == 0x6c )
s.add(flag[10] ^ flag[7] ^ flag[8] == 0x3d )
s.add(flag[0xd] ^ flag[10] ^ flag[0xb] == 0x70 )
s.add(flag[0x10] ^ flag[0xd] ^ flag[0xe] == 0x34 )
s.add(flag[0x13] ^ flag[0x10] ^ flag[0x11] == 0x5a )
s.add(flag[0x16] ^ flag[0x13] ^ flag[0x14] == 1 )
s.add(flag[0x19] ^ flag[0x16] ^ flag[0x17] == 10 )
s.add(flag[0x1c] ^ flag[0x19] ^ flag[0x1a] == 0x2d )
s.add(flag[0x1f] ^ flag[0x1c] ^ flag[0x1d] == 0x43 )
s.add(flag[0x22] ^ flag[0x1f] ^ flag[0x20] == 0x27 )
s.add(flag[0x25] ^ flag[0x22] ^ flag[0x23] == 0x3f )
s.add(flag[6] ^ flag[0] ^ flag[4] == 0x75 )
s.add(flag[10] ^ flag[4] ^ flag[8] == 0x25 )
s.add(flag[0xe] ^ flag[8] ^ flag[0xc] == 0x34 )
s.add(flag[0x12] ^ flag[0xc] ^ flag[0x10] == 0x66 )
s.add(flag[0x16] ^ flag[0x10] ^ flag[0x14] == 4 )
s.add(flag[0x1a] ^ flag[0x14] ^ flag[0x18] == 0x36 )
s.add(flag[0x1e] ^ flag[0x18] ^ flag[0x1c] == 0x76 )
s.add(flag[0x22] ^ flag[0x1c] ^ flag[0x20] == 0x3b )
s.add(flag[7] ^ flag[1] ^ flag[5] == 0x6a )
s.add(flag[0xb] ^ flag[5] ^ flag[9] == 0x31 )
s.add(flag[0xf] ^ flag[9] ^ flag[0xd] == 0x2e )
s.add(flag[0x13] ^ flag[0xd] ^ flag[0x11] == 0x5e )
s.add(flag[0x17] ^ flag[0x11] ^ flag[0x15] == 10 )
s.add(flag[0x1b] ^ flag[0x15] ^ flag[0x19] == 0x33 )
s.add(flag[0x1f] ^ flag[0x19] ^ flag[0x1d] == 6 )

print(s.check())
if(str(s.check()) == "sat"):
	l = [flag[0],flag[1],flag[2],flag[3],flag[4],flag[5],flag[6],flag[7],flag[8],flag[9],flag[10],flag[11],flag[12],flag[13],flag[14],flag[15],flag[16],flag[17],flag[18],flag[19],flag[20],flag[21],flag[22],flag[23],flag[24],flag[25],flag[26],flag[27],flag[28],flag[29],flag[30],flag[31],flag[32],flag[33],flag[34],flag[35],flag[36],flag[37]]
	f = ''.join([chr(s.model()[i].as_long()) for i in l ])
	print(f)
$ ./z3al.py 
sat
pesuctf{3qu4710n5_d0n7_b07h3r_4nym0r3}

FLAG : pesuctf{3qu4710n5_d0n7_b07h3r_4nym0r3}

FOOBAR CTF 2021

I was the author for the reverse questions.

  • net_dot
  • baby_rev
  • child_rev
  • wargames
  • Numerical computing
  • not_only_z3

NET DOT

link to question link to c sharp file

It was a .dll file, by name it was clear that it was a dot net file.

Solver Script

#!/usr/bin/env python3

enc = [2410, 2404, 2430, 2408, 2391, 2381, 2333, 2396, 2369, 2332, 2398, 2422, 2332, 2397, 2416, 2370, 2393, 2304, 2393, 2333, 2416, 2376, 2371, 2305, 2377, 2391]

sum_all = ord('G') ^ 2410

flag = ''

for i in range(len(enc)):
    flag += chr((enc[i]^sum_all) + ((i%2)*2 + (i%3)*1))

print(flag)

FLAG : GLUG{d0tn3t_1s_qu1t3_go0d}

CHILD REV

link to question

Solver script

#!/usr/bin/env python3

def key_gen():
    # adding ascii value of "G","L","U","G"
    key = ord('G') + ord('L') + ord('U') + ord('G')
    # logical shift left by 4 twice, basically lsl by 8
    key = key << 4
    key = key << 4
    return key


# ARRAY IS GIVEN
arr = [77688,77616,77682,77663,77665,77678,77668,77663,77676,77616,77671,77617,77667,77632,77676,77663,77683,77672,77617,77670,77684,77663,77669,77632,77683,77689,77663,77682,77617,77671,77672,77624,77631,77631]

key = key_gen()
print('GLUG{',end='')
for i in arr:
    print(chr(i ^ key),end='')
print('}')

FLAG : GLUG{x0r_and_l0g1c@l_sh1ft_e@sy_r1gh8??}

BABY REV

link to question link to nasm file

As the question was using logical shift right by the value of 2 for encryption. The last 2 bytes for every number was getting lost , so there are so many possible password combinatoins . Any one of them will give you the flag.

FLAG : GLUG{intro_to_assembly}

WARGAMES

link to file

chall : nc chall.nitdgplug.org 30419

solver script

t = [159, 218, 153, 214, 45, 206, 153, 374]

print("Launchcode : ",end='')
for i in range(0,len(t),2):
    print(chr((t[i]^69)>>1),end='')
    print(chr((t[i+1]^10)>>2),end='')

sol = [192, 18, 117, -32, 120, -16, 173, -2]
key = "PEACEOUT"
res = []
for i in range(len(sol)):
    if i & 1 == 1:
        res.append(chr((ord(key[i]) - sol[i])))
    else:
        res.append(chr(((sol[i]) - ord(key[i]))))

for i in res:
    print(i,end='')

KEY = "There's no way to win"
DICT = "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%`+^&*(){}[]\";?'\/<>~=:-_.   |,"
I = 7
S = [123, 47, 86, 28, 74, 50, 32, 114]
KEYOUT = []
RESULT = []
for i in S:
    for X in DICT:
        DATA=(ord(X) + I ^ ord(KEY[I])) % 255
        if DATA==i:
            KEYOUT.append(DATA)
            I = (I + 1) % len(KEY)
            RESULT.append(X)
            break
for i in RESULT:
    print(i,end='')
print()

Launchcode : m4n741n_p34c3_XVT9022GLD

FLAG : GLUG{15_7h15_r34l_0r_15_17_g4m3??}

Numerical Computing

link to question

This was simple fortran program.

program question

    implicit none

! Type declarations
    character(len=18) :: inp
    character(len=18) :: enc
    character :: c1,c2,c
    integer :: n,x,x1,x2,f
    integer, dimension (18) :: num, num1, num2
    f=0
    enc = "QWERTYUIOPASDFGHJK"
    num = (/352, 108, 256, 84, 752, 160, 1648, 480, 1968, 204, 592, 404, 1792, 456, 576, 168, 1968, 216/)
    print*,"Enter the flag : "
    read(*,*)inp
    do n = 1,18
        c1 = enc(n:n)
        c2 = inp(n:n)
        x1 = IACHAR(c1)
        x2 = IACHAR(c2)
        num2(n) = XOR(x1,x2)
    end do


    do n = 1, 18
        if(MOD(n-1,2) .eq. 1) then
            num1(n) = LSHIFT(num2(n), 2)
        else
            num1(n) = LSHIFT(num2(n), 4)
        end if
    end do

    do n=1,18
        if(num1(n) == num(n)) then
            f = f+1
        end if
    end do
    if(f == 18) then
        print*,"you got it"
    else
        print*,"Wrong"
    end if

end program question

solver script

#!/usr/bin/env python3

enc = [352, 108, 256, 84, 752, 160, 1648, 480, 1968, 204, 592, 404, 1792, 456, 576, 168, 1968, 216]
enc1 = []

for i in range(len(enc)):
    if i&1:
        enc1.append(enc[i] >> 2)
    else:
        enc1.append(enc[i] >> 4)

enc_text = 'QWERTYUIOPASDFGHJK'

flag = ''

for i in range(len(enc1)):
    flag += chr(ord(enc_text[i]) ^ enc1[i])
print(flag)

FLAG : GLUG{q214cd644cb1}

NOT_ONLY_Z3

link to question

simple graph

input -> md5 -> shuffling of md5 -> checking 30 equations for validity.

sol:

1.>cracking the solution of equation by z3.

2.>deshuffling the cracked solution.

3.>cracking the md5 to get the password. (Note: the password doesnt exist in rockyou.txt)

Z3 Solve script

#!/usr/bin/env python3

from z3 import *

flag_hash = ''
for it in range(6):
	a = Real('a')
	b = Real('b')
	c = Real('c')
	d = Real('d')
	e = Real('e')
	s = Solver()
	if it == 0:
		s.add(9*a + 3*b + 8*c + 4*d + 2*e == 1328,6*a + 7*b + 7*c + 6*d + 7*e == 1685,4*a + 5*b + 4*c + 4*d + 6*e == 1176,9*a + 3*b + 1*c + 4*d + 7*e == 1245,1*a + 1*b + 7*c + 1*d + 7*e == 862)
	elif it == 1:
		s.add(1*a + 2*b + 4*c + 2*d + 8*e == 1277,9*a + 9*b + 4*c + 3*d + 8*e == 2151,7*a + 3*b + 6*c + 6*d + 1*e == 1302,3*a + 6*b + 4*c + 1*d + 1*e == 852,9*a + 5*b + 9*c + 4*d + 4*e == 1871)
	elif it == 2:
		s.add(6*a + 7*b + 9*c + 2*d + 3*e == 1724,6*a + 9*b + 3*c + 2*d + 5*e == 1712,4*a + 6*b + 6*c + 9*d + 3*e == 1703,4*a + 6*b + 7*c + 7*d + 2*e == 1605,1*a + 6*b + 7*c + 9*d + 2*e == 1551)
	elif it == 3:
		s.add(6*a + 8*b + 4*c + 4*d + 2*e == 1822,5*a + 5*b + 4*c + 6*d + 3*e == 1784,5*a + 7*b + 4*c + 1*d + 5*e == 1800,6*a + 3*b + 9*c + 1*d + 7*e == 2399,3*a + 7*b + 5*c + 5*d + 2*e == 1622)
	elif it == 4:
		s.add(1*a + 6*b + 6*c + 9*d + 1*e == 1263,9*a + 1*b + 6*c + 1*d + 9*e == 1370,4*a + 7*b + 6*c + 9*d + 5*e == 1686,3*a + 6*b + 7*c + 5*d + 2*e == 1250,4*a + 8*b + 1*c + 5*d + 3*e == 1157)
	elif it == 5:
		s.add(1*a + 8*b + 5*c + 4*d + 9*e == 1400,1*a + 6*b + 3*c + 8*d + 1*e == 1012,5*a + 6*b + 1*c + 7*d + 8*e == 1427,1*a + 4*b + 5*c + 5*d + 2*e == 895,2*a + 3*b + 7*c + 7*d + 3*e == 1163)
	s.check()
	m = s.model()
	vs = [(str(v),chr(int(str(m[v])))) for v in m]
	arr = ['0']*5
	for i in vs:
		arr[ord(i[0])-ord('a')] = i[1]
	for i in arr:
		flag_hash += str(i)
flag_hash += '7'
flag_hash += '3'

print(flag_hash)

$ ./solver.py 
401749466c2b507f1c8c694836338373

reshuffle to get the actual md5 string

reshuffle script

#include<stdio.h>

int main(int argc, char const *argv[])
{
	char inp[33];
	scanf("%s",inp);
	int ar[5][5];
	for(int i = 0;i < 25;i++)
		ar[(int)(i/5)][i%5] = (int)inp[i];
	printf("\nMATRIX : \n");
	for(int i = 0;i< 5; i++){
		for(int j = 0; j < 5; j++){
			printf("%d,",ar[i][j]);
		}
		printf("\n");
	}
	for(int i = 0;i< 5; i++){
		for(int j = 0; j < 2; j++){
			ar[i][j] ^= ar[i][3+j];
			ar[i][3+j] ^= ar[i][j];
			ar[i][j] ^= ar[i][3+j];
		}
	}
	printf("\nMATRIX : \n");
	for(int i = 0;i< 5; i++){
		for(int j = 0; j < 5; j++){
			printf("%d,",ar[i][j]);
		}
		printf("\n");
	}
	for(int i = 0;i < 25;i++)
		inp[i] = (char)ar[(int)(i/5)][i%5];
	printf("\nShuffled string : %s\n",inp);

	return 0;
}
$ ./test 
401749466c2b507f1c8c694836338373

MATRIX : 
52,48,49,55,52,
57,52,54,54,99,
50,98,53,48,55,
102,49,99,56,99,
54,57,52,56,51,

MATRIX : 
55,52,49,52,48,
54,99,54,57,52,
48,55,53,50,98,
56,99,99,102,49,
56,51,52,54,57,

Shuffled string : 741406c6940752b8ccf1834696338373

final output : 741406c6940752b8ccf1834696338373

If we crack this md5 hash we will get p4ssw0rd! (it can be crackable in crackstation.net)

Getting the flag

$ ./not_only_z3 
Enter the string : p4ssw0rd!

Conratulations : GLUG{p4ssw0rd!_401749466c2b507f1c8c694836338373}

FLAG : GLUG{p4ssw0rd!_401749466c2b507f1c8c694836338373}