This is a write-up for shop under the reverse engineering category available at:
https://play.picoctf.org/login?redirect=/practice/challenge/134

Downloading the file and making it executable with:

wget <link>
chmod +x source

From running the executable I gathered that:

  1. I can buy/sell items
  2. I have 40 coins
  3. Item number 3’s name is Fruitful Flag (100 coins) which is peculiar so if I buy that I might get the flag perhaps

First lets try to mess with the binary with all the wrong inputs trying to break it.

I tried buying negative amount of item 1 and I gained coin. Which means now I can buy the flag item. Buying the flag gives an ASCII output which after concatenating the values you get the flag.

Well that was dumb. Let’s do this the fun way!

I will use gdb and try to get the flag assuming that this software got patched and I cant break it that easily.

gdb source
(gdb) disass main
> Function "main" not defined.

I tried to disassemble main but main is not defined so:

(gdb) info functions
> File /opt/hacksports/shared/staging/Shop_0_3803762289926176/problem_files/source.go:
void main.check(error);
void main.get_flag(void);
void main.main(void);
void main.menu([]main.item, []main.item, int, []main.item, []main.item, int);
void main.openShop(void);
void main.stockUp([]main.item, []main.item);

These are the functions in source.go.
The function main.get_flag(void) will most likely give us the flag.

So I’m going to start from main.main and see where its getting called so I just jump to that address see if I can skip having enough coins.

(gdb) disass main.main
> Dump of assembler code for function main.main:
.
.
.
0x080d3337 <+7>: mov -0x4(%ecx),%ecx
0x080d333d <+13>: cmp 0x8(%ecx),%esp
0x080d3340 <+16>: jbe 0x80d3348 <main.main+24>
0x080d3342 <+18>: call 0x80d3350 <main.openShop>
.
.
.

at 0x080d3342 <+18> we call main.openShop

(gdb) disass main.openShop

openShop calls main.stockUp and main.menu. stockUp doesn’t sound relevant so lets focus on menu.

(gdb) disass main.menu
>
.
.
.
0x080d3ebf <+1375>: mov %ebp,0x24(%esp)
0x080d3ec3 <+1379>: call 0x80d4440 <main.get_flag>
0x080d3ec8 <+1384>: mov 0xa8(%esp),%ecx
.
.
.

After reading through all of that at 0x080d3ec3 <+1379> we call the main.get_flag function.
So let’s put a breakpoint at main.menu and then jump to the flag function.

(gdb) b main.menu
> Breakpoint 2 at 0x80d3960
(gdb) run
> Thread 1 "source" hit Breakpoint 2, main.menu (inv=..., user=..., wallet=40, ~r3=..., ~r4=..., ~r5=0) at /opt/hacksports/shared/staging/Shop_0_3803762289926176/problem_files/source.go:50
50 in /opt/hacksports/shared/staging/Shop_0_3803762289926176/problem_files/source.go
(gdb) jump *0x080d3ec3
> Flag is:

And here we go! If the solution is boring look for a better one!