This declaration
int *obj1[N];
indeed declares an array of objects of the pointer type int *.
This declaration
int *obj2;
declares an object of the type int * and in the next statement
obj2 = malloc(N*sizeof(int));
there is allocated memory for an array of N elements of the type int.
So in this lines
val1 = *obj1[i];
val2 = obj2[i];
that for clarity are better to rewrite like
int val1 = *obj1[i];
int val2 = obj2[i];
you get objects of the type int. In the first line the expression obj1[i] yields an object of the type int * because obj1 is an array of pointer. So to get the pointed object of the type int you need to dereference the pointer expression obj1[i]. In the second line the expression obj2[i] yields an object of the type int because there was allocated an array of integers.
If you want to allocate an array of pointers of the type int * you have to write
int **obj2 = malloc(N*sizeof(int *));
In this case to access elements of the both arrays you can write
int val1 = *obj1[i];
int val2 = *obj2[i];
Pay attention to that in this expression obj1[i] the array designator obj1 is implicitly converted to a pointer of the type int ** to its first element. So the both expressions obj1[i] and obj2[i] are equivalently evaluated. Also the both expressions *obj1[i] and *obj2[i] are equivalent to obj1[i][0] and obj2[i][0].
On the other hand, you could also write for example
int **obj3 = obj1; // the array is implicitly converted to pointer
//...
int val3 = *obj3[i];
Bear in mind that according to the C Standard (6.5.2.1 Array subscripting)
2 A postfix expression followed by an expression in square brackets []
is a subscripted designation of an element of an array object. The
definition of the subscript operator [] is that E1[E2] is identical to
(*((E1)+(E2))). Because of the conversion rules that apply to the
binary + operator, if E1 is an array object (equivalently, a pointer
to the initial element of an array object) and E2 is an integer,
E1[E2] designates the E2-th element of E1 (counting from zero)